Vue.js components internal state being reused when underlying data changes

感情迁移 提交于 2019-12-12 09:39:32

问题


I am working on a medium size web application based on vue.js. I've been facing several virtual DOM issues mostly related to vue instances life cycle.

The following code snippet (jsFiddle also available here) demonstrates some of these problems. The test-component vue component receives a property value and updates its internal state using that value.

Whenever the data set changes (by sorting or by new data), the properties are updated, but the internal state is not. This is pretty easy to see by running the code snippet and clicking on the buttons.

I understand the data component attribute is a function and it looks like it is invoked only when the component is created. That kind of explains what is going on. The thing is I don't know how to achieve the intended behavior which is: all the children components internal state to be updated whenever the data source changes.

  1. Is there a life cycle callback that triggers when the component is
    "refreshed"? I want a component refresh only callback. Do I need to watch for prop changes individually? That would be ugly.
  2. Is there a clean way to update the internal state when the props change?
  3. Is it possible to destroy all children components and force them to be recreated? I know this is not the best option but it would solve all my data binding problems :)
  4. How does vue decides when a component will be released or reused? In my example components go away when the data set size changes from 4 to 3, but the first 3 items internal state don't change so the first three items are being recycled.

Moving all the state to vuex would be a possible solution but some components are generic and I don't want them to contain knowledge about the vuex store details. Actually I am using vuex for most components, but for truly generic components I don't think it is a good option.

var testComponent = Vue.component('test-component', {
  template: '#component_template',
  props: ['prop1'],
  data: function(){
    return {
      internalState: this.prop1 
    }
  }
})

new Vue({
  el: "#app",
  data: function(){
    return {
      items: [
        'Item 1',
        'Item 2',
        'Item 3'
      ],
      dataToggle: true,
      sorted: true
    };
  },
  methods: {
    sortDataSet: function(){
      if(this.sorted){
        this.items.reverse();
      } else {
        this.items.sort;
      }
    }
    ,changeDataSet: function(){
      if(this.dataToggle){
        this.items = ['Item 4', 'Item 5', 'Item 6', 'Item 7'];
      } else {
        this.items = ['Item 1', 'Item 2', 'Item 3'];
      }
      
      this.dataToggle = !this.dataToggle;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.2/vue.js"></script>
<body>
  <h3>
    Components internal state is not being updated
  </h3>
  <div id="app">
    <button v-on:click="changeDataSet">
      Change data
    </button>
    <button v-on:click="sortDataSet">
      Sort data
    </button>
    <ul>
      <li v-for="item in items">
        <test-component :prop1="item">
        </test-component>
      </li>
    </ul>
  </div>
</body>

<script id="component_template" type="x-template">
	<div>Prop: {{prop1}} || Internal state: {{internalState}}</div>
</script>

回答1:


Use a key.

It is recommended to provide a key with v-for whenever possible, unless the iterated DOM content is simple, or you are intentionally relying on the default behavior for performance gains.

<li v-for="item in items" :key="item">
    <test-component :prop1="item">
    </test-component>
</li>

Updated fiddle.



来源:https://stackoverflow.com/questions/43765209/vue-js-components-internal-state-being-reused-when-underlying-data-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!