Why does my Vue component require :key?

后端 未结 4 1180
渐次进展
渐次进展 2020-12-11 18:16

I have a small Vue.js component which displays a favorite star icon. Clicking on the icon favorites/unfavorites the element. So far I have only implemented the UI part, whic

相关标签:
4条回答
  • 2020-12-11 18:30

    You shouldn't need the :key, it's only necessary in v-for loops. I would suggest you remove it and replace your v-show with a v-if and v-else directive.

      <i v-if="favorite" class="text-warning fas fa-star"></i>
      <i v-else class="text-warning far fa-star"></i>
    

    v-if removes and addes the section to the DOM whereas v-show just hides it so this way well resolve your issue

    0 讨论(0)
  • 2020-12-11 18:45

    Ok I think the problem here is that you're changing your root data object. To preserve reactivity, you shouldn't change the root data object after you've instantiated Vue.

    Here is your code in a simple Vue. I didn't need :key to make it work. I would keep :key for inside loops.

    markup

    <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>
    

    code

    vm = new Vue({
      el : "#vueRoot",
      data() {
        return { store :{
          favorite: true
        }}
      },
      mounted() {
      },
      methods: {
        toggleFavorite() {
          this.store.favorite = !this.store.favorite
        }
      }
    }
    );
    

    This is a working example with minimal changes. From what you've showed us, you should just have <i> element, then do what you want with a dynamic class list, like...

    <i :class="['text-warning','fa-star',store.favorite?'fas':'far']"></i>
    
    0 讨论(0)
  • 2020-12-11 18:50

    Its seems to be a general issue of FontAwesome CSS regardless the framework. There is an issue on github and here the same issue with react https://github.com/FortAwesome/Font-Awesome/issues/11967

    To prove that, here is a simplified version of the same example but using 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>

    0 讨论(0)
  • 2020-12-11 18:50

    Vue patches with the virtual DOM whenever it is necessary. That is, whenever vue detects the changes on the DOM, it patches them for faster performance. And patching in the DOM will not change the icon or image. You need to replace the DOM instead.

    Thus, vue provides the way for us whenever we need to change the DOM by replacing method, we can use :key binding.

    So, :key binding can be used to force replacement of an element/component instead of reusing it.

    The following whole html div will be replaced whenever there is change in favorite data as we're :key binding on it:

    <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>
    

    This is why vue forcefully allows us to use :key binding inside a loop as there's need of replacing the elements inside the loop whenever it detects the changes in the data. This is made compulsory from 2.2.0+ and ESLint also have implemented this feature so that if you miss :key binding inside the loop, then you'll see the error on that line when you use editor that supports eslint, so that you can fix the error.

    Just an opinion, the strict requirement of the :key binding should be removed from the vue as we might want a loop of predefined data and don't want to change the DOM but we still use the v-for loop for listing bigger data. But it might be rare case though.


    Read carefully on the documentation for :key binding and then you'll have an idea.

    The :key binding can be useful when you want to:

    Properly trigger lifecycle hooks of a component

    Trigger transitions


    1. Use :key binding to replace the DOM. Remember it slower the performance as it replace the whole DOM that is bound to the element.
    2. Don't use :key binding when you don't want to replace the DOM or you think there's no data changes detection required. This will allow vue to perform better without :key binding.
    0 讨论(0)
提交回复
热议问题