Почему мой компонент Vue требует: key?
у меня есть небольшой Vue.JS компонент, который отображает значок любимой звезды. Нажав на значок "избранное" /unfavorites элемент. До сих пор я реализовал только часть пользовательского интерфейса, которая выглядит так:
<template>
<div :key="favorite">
<a v-on:click="toggleFavorite" style="cursor: pointer">
<i v-show="favorite" class="text-warning fas fa-star"></i>
<i v-show="!favorite" class="text-warning far fa-star"></i>
</a>
</div>
</template>
<script>
export default {
data() {
return {
favorite: true,
}
},
mounted() {
},
methods: {
toggleFavorite() {
this.favorite = !this.favorite
}
},
props: ['team-id'],
}
</script>
<style scoped>
</style>
как вы можете видеть, логика довольно проста.
это работает хорошо, но меня беспокоит то, что, если я удалю :key
свойство из моего шаблона, значок не обновляется, когда я нажимаю на него (хотя я проверил, что базовый собственность is действительно правильно обновить). Добавление :key
заставляет его работать, я думаю, потому что он заставляет Vue.js для полного повторного отображения компонента, когда favorite
обновляется.
Почему это происходит? Я довольно новичок в мире фреймворков JS, поэтому простите любые очевидные вещи, которые я мог бы пропустить. Я провел некоторое исследование в интернете, но не смог найти объяснения. Я просто хочу убедиться, что я делаю все правильно, а не просто взламываю проблему здесь.
4 ответов
похоже, что это общая проблема FontAwesome CSS независимо от структуры. Существует проблема на github и здесь та же проблема с react https://github.com/FortAwesome/Font-Awesome/issues/11967
чтобы доказать это, вот упрощенная версия того же примера, но с использованием bootstrap icons
new Vue({
el: '#app',
data() {
return {
fav: true
}
}
});
<script
src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"
></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div id="app">
<div>
<a v-on:click="fav = !fav" style="cursor: pointer">
<i v-show="fav" class="glyphicon glyphicon-star"></i>
<i v-show="!fav" class="glyphicon glyphicon-star-empty"></i>
</a>
</div>
</div>
Vue патчи с виртуальным DOM, когда это необходимо. То есть, когда vue обнаруживает изменения на DOM, он исправляет их для более быстрой производительности. И исправление в DOM не изменит значок или изображение. Вместо этого вам нужно заменить DOM.
таким образом, vue предоставляет нам путь, когда нам нужно изменить DOM путем замены метода, мы можем использовать :key
привязка.
и :key
binding можно использовать для принудительной замены элемент / компонент вместо повторного использования.
следующий весь HTML div будет заменен всякий раз, когда есть изменение в favorite
данные, как мы :key
привязка к нему:
<div :key="favorite">
<a v-on:click="toggleFavorite" style="cursor: pointer">
<i v-show="favorite" class="text-warning fas fa-star"></i>
<i v-show="!favorite" class="text-warning far fa-star"></i>
</a>
</div>
вот почему vue насильно позволяет нам использовать :key
привязка внутри цикла, поскольку необходимо заменить элементы внутри цикла всякий раз, когда он обнаруживает изменения в data
. Это делается обязательным из 2.2.0+
и ESLint также реализовали эту функцию, чтобы, если вы Мисс :key
привязка внутри цикла, затем вы увидите ошибку в этой строке при использовании редактора, поддерживающего eslint, чтобы вы могли исправить ошибку.
просто мнение, строгое требование :key
привязка должна быть удалена из vue, поскольку нам может понадобиться цикл predefined data
и не хотите менять DOM, но мы все еще используем v-for
петли для перечисления больших данных. Но это может быть редкий случай.
внимательно прочитайте документация :комбинации клавиш и тогда у вас появится идея.
на :key
привязка может быть полезна, если вы хотите:
правильно триггерные крючки жизненного цикла компонента
триггер переходы
- использовать
:key
привязка для замены DOM. Помните, что это замедляет производительность, поскольку она заменяет весь DOM, который привязан к элементу. - не используйте
:key
привязка, когда вы не хотите заменять DOM или вы думаете, что нетdata
обнаружение изменений, необходимых. Эта воля позвольте vue работать лучше без:key
привязка.
вам не нужен ключ:, это необходимо только в V-для циклов. Я бы предложил вам удалить его и заменить ваше v-шоу директивой v-if и v-else.
<i v-if="favorite" class="text-warning fas fa-star"></i>
<i v-else class="text-warning far fa-star"></i>
v-Если удаляет и добавляет раздел в DOM, тогда как v-show просто скрывает его, чтобы таким образом решить вашу проблему
Ok Я думаю, что проблема здесь в том, что вы меняете свой корневой объект данных. Чтобы сохранить реактивность, не следует изменять корневой объект данных после создания экземпляра Vue.
здесь код в простом Vue. Мне не нужен был ключ, чтобы заставить его работать. Я бы сохранил :ключ для внутренних петель.
разметки
<div id="vueRoot">
<a v-on:click="toggleFavorite" style="cursor: pointer">
<i v-show="store.favorite" class="text-warning fas fa-star">Fav</i>
<i v-show="!store.favorite" class="text-warning far fa-star">Not fav</i>
</a>
</div>
код
vm = new Vue({
el : "#vueRoot",
data() {
return { store :{
favorite: true
}}
},
mounted() {
},
methods: {
toggleFavorite() {
this.store.favorite = !this.store.favorite
}
}
}
);
Это рабочий пример с минимальными изменениями. От чего вы показали нам, вы должны просто иметь элемент , а затем делать то, что хотите, с динамическим списком классов...
<i :class="['text-warning','fa-star',store.favorite?'fas':'far']"></i>