【问题标题】:Cleanest way to re-render component in Vue在 Vue 中重新渲染组件的最简洁方法
【发布时间】:2020-03-05 08:38:07
【问题描述】:

我有一个 Keyboard.vue 组件,其中包含许多 Key.vue 子组件实例(每个键一个)。

Key.vue 中,键实际上是一个可以被禁用的html <button> 元素。

通过单击我的应用程序中的某个按钮,我想重置键盘并再次启用所有键。我认为将v-if 设置为false 然后再设置为true (<keyboard v-if="BooleanValue" />) 会重新渲染Keyboard.vue 及其所有Key.vue 子组件实例。

它没有。为什么不呢?

App.vue

<template>
  <div class="app">
    ...
    <keyboard v-if="!gameIsOver && showKeyboard" />
    ...
  </div>
</template>

<script>
export default {
  components: {
    Keyboard
  },
  computed: {
    gameIsOver () {
      return this.$store.state.gameIsOver
    },
    showKeyboard () {
      return this.$store.state.showKeyboard
    }
  }

Keyboard.vue

<template>
  <section>
    <key class="letter" v-for="(letter) in letters" :key="letter" :letter="letter" />
  </section>
</template>

Key.vue

<template>
  <button :disabled="disabled" @click="checkLetter(letter)">
    {{ letter }}
  </button>
</template>

<script>
export default {
  ...
  data () {
    return {
      disabled: false
    }
  }

我的按钮重置键盘触发器:

this.$store.commit('SET_KEYBOARD_VISIBILITY', false)
this.$store.commit('SET_KEYBOARD_VISIBILITY', true)

【问题讨论】:

  • 你能发布你的代码吗?
  • 好的,我刚刚编辑了问题
  • 它应该自动重新渲染组件。事实上,它不太可能意味着您的变量不是反应性的,或者以无法检测到的方式被覆盖。由于 Key.vue 中的变量 disabled 突然出现,我无法真正检查变量的来源或修改方式。
  • 至于您的其他问题:重新渲染仅在下一个刻度发生。如果您在一个刻度内修改了两次变量,它将只使用最后一个值进行下一次重新渲染
  • @Sumurai8 我在下一个刻度中将变量设置回true,现在它可以工作了,谢谢!我认为您做出回答(我会接受)可能是值得的,因为我怀疑很多人不知道这一点。

标签: vue.js components vue-reactivity


【解决方案1】:

首先要回答您的问题,重新渲染 Vue 组件或任何元素的最简洁方法是将其 key 属性绑定到将控制重新渲染的反应性事物,每当键值更改时,它将触发重新渲染。

要为每次渲染创建这样一个唯一键,我可能会使用递增的数字,并且每当我想重新渲染时,我都会递增它。

<template>
<div>
  <div :key="renderKey">
  </div>
</div>
</template.

<script>
export default {
  data: () => ({
    renderKey: 0
  }),
  methods: {
    reRender() {
       this.renderKey++;
    }
  }
};
</script>

现在至于为什么切换 v-if 不起作用:在 true 和 false 之间切换反应性属性不一定会触发 2 次重新渲染,因为 Vue 有一个异步更新队列,它在特定时间范围内应用补丁中的 DOM 更改,而不是每个单独的更新。这就是为什么 Vue 如此快速和高效的原因。

所以你触发disabledfalse,然后到true。渲染器将​​决定不更新 DOM,因为最终值与上次相比没有变化,如果我没记错的话,时间大约是 16 毫秒。因此,您可以通过在 truefalse 之间切换道具之间等待超过 16 毫秒来完成这项工作,我说“可以”而不是“应该”。

【讨论】:

  • 多组件呢?
【解决方案2】:

最干净的方法是在可以重置它的地方设置禁用状态,因为重新渲染组件以重置它会利用破坏和重新创建组件的副作用。这让某人很难弄清楚为什么按钮再次启用,因为在您重新渲染时,没有任何代码将 disabled 变量更改为 false

也就是说,您会看到您当前的行为,因为 Vue 聚合了当前“tick”的所有更改,并且仅在该tick 结束时重新渲染。这意味着如果您将变量设置为 false,然后设置为 true,它将只使用最后一个值。

// Nothing happens
this.showSomething = false
this.showSomething = true

要强制它重新渲染,您可以使用 Amitha 展示的技巧,使用 key。由于 Vue 将为每个键值使用一个实例,因此更改键将破坏旧键并创建一个新键。或者,您可以使用this.$nextTick(() =&gt; { ... }) 来强制您的某些代码在下一次运行时运行。

// Destroy all the things
this.showSomething = false
this.$nextTick(() => {
  // Okay, now that everything is destroyed, lets build it up again
  this.showSomething = true
});

【讨论】:

  • 谢谢。我再次编辑以显示disabled 是一个常规数据变量。我同意您回答的第一句话,但是如何在所有关键组件实例中同时将 disabled 设置为 false
【解决方案3】:

您能否尝试为键盘设置一个 :key,如下所示

<keyboard v-if="!gameIsOver && showKeyboard" :key="increment" /> 

“增量”:本地组件属性

当您需要重新渲染视图时,将“increment”属性值加一。使用 vuex 存储属性与本地“增量”属性同步。

如何将 vuex 值更改与本地属性同步:添加一个“观察者”来观察 vuex 存储属性更改并将该更改分配给我们设置为键盘“键”的本地“增量”属性

【讨论】:

    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    相关资源
    最近更新 更多