2

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

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

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

它没有。为什么不?

应用程序.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
    }
  }

键盘.vue

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

键.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)
4

3 回答 3

2

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

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

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

要强制它重新渲染,您可以使用 Amitha 展示的技巧,使用 key。由于 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
});
于 2019-11-08T18:03:55.947 回答
2

首先要回答您的问题,重新渲染 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 毫秒。true因此,您可以通过在和之间切换道具之间等待超过 16 毫秒来完成这项工作false,我说“可以”而不是“应该”。

于 2019-11-08T20:29:27.793 回答
0

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

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

“增量”:本地组件属性

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

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

于 2019-11-08T17:53:04.847 回答