在 Vue 中重新渲染组件的最简洁方法

Cleanest way to re-render component in Vue

我有一个 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 如下所示

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

"increment":本地组件属性

并在需要重新渲染视图时将 "increment" 属性 值增加一。使用 vuex store 属性 与本地同步 "increment" 属性.

how to sync vuex value changes with local 属性: add a "watcher" watch the vuex store 属性 changes and assigned that change to the local "increment" 属性 我们设置为键盘 "key"

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

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

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

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

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

首先回答你的问题,重新渲染 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 毫秒来完成这项工作,我说 "could" 而不是 "should".