Самый чистый способ перерисовки компонента в Vue - PullRequest
1 голос
/ 08 ноября 2019

У меня есть 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)

Ответы [ 3 ]

0 голосов
/ 08 ноября 2019

Самый чистый способ - это иметь отключенное состояние где-нибудь, где вы можете сбросить его, потому что повторный рендеринг вашего компонента для его сброса использует побочный эффект разрушения и воссоздания ваших компонентов. Кому-то становится трудно выяснить , почему кнопки снова включены, потому что нет кода, изменяющего переменную disabled на false в любом месте, которое вызывается при повторном рендеринге.

Тем не менее, вы видите свое текущее поведение, потому что Vue агрегирует все изменения текущего "тика" и повторяет только в конце этого тика. Это означает, что если вы установите для вашей переменной значение false, тогда для true будет использоваться только последнее значение.

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

Чтобы принудительно выполнить повторный рендеринг, вы можете использовать трюк, который показывает Амитха, используя ключ. Поскольку 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
});
0 голосов
/ 08 ноября 2019

Чтобы ответить на ваш вопрос в первую очередь, самый чистый способ перерисовки компонента Vue или любого элемента - это привязать его атрибут key к чему-то реактивному, что будет контролировать повторные визуализации, всякий раз, когда изменяется значение ключа, он вызываетre-render.

Чтобы сделать такой уникальный ключ для каждого рендера, я, вероятно, использовал бы увеличенное число, и всякий раз, когда я хотел бы сделать рендеринг, я увеличивал его.

<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 такой быстрый и эффективный.

Таким образом, вы запускаете disabled до false, а затем до true. Рендерер решит не обновлять DOM, поскольку окончательное значение не изменилось с прошлого раза, время составляет около 16 мс. Если я правильно помню. Таким образом, вы можете сделать эту работу, подождав более 16 мс между переключением вашей опоры между true и false, я говорю «мог», но не «должен».

0 голосов
/ 08 ноября 2019

Не могли бы вы попробовать установить: клавишу для клавиатуры, как показано ниже

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

«приращение»: свойство локального компонента

и увеличить значение свойства «приращение» на единицукогда вам нужно перерисовать вид. используйте свойство хранилища vuex для синхронизации с локальным свойством «increment».

как синхронизировать изменения значения vuex с локальным свойством: добавьте «watcher», чтобы наблюдать за изменениями свойства хранилища vuex и назначить это изменение локальному »приращение "свойство, которое мы установили как" ключ "для клавиатуры

...