2017-05-03 79 views
2

我正在研究基于vue.js的中型Web应用程序。我一直在面对几个与vue实例生命周期相关的虚拟DOM问题。Vue.js组件内部状态在底层数据更改时被重用

以下代码片段(jsFiddle也可用here)演示了其中一些问题。 测试组件 vue组件接收一个属性值并使用该值更新其内部状态。

无论何时数据集更改(通过排序或新数据),属性都会更新,但内部状态不会更新。通过运行代码片段并单击按钮,这很容易看到。

我了解数据组件属性是一个函数,它看起来像只有在创建组件时才调用它。这种解释发生了什么。事情是我不知道如何实现预期的行为,即:所有的子组件内部状态都会在数据源发生更改时更新

  1. 有触发组件时
    “刷新”生命周期回调?我想要一个组件只刷新回调。我是否需要单独观察道具变化?那会很难看。
  2. 有没有一种干净的方式来更新道具改变时的内部状态?
  3. 是否有可能销毁所有儿童组件并强制它们被重新创建?我知道这不是最好的选择,但它可以解决我所有的数据绑定问题:)
  4. vue如何决定组件何时被释放或重用?在我的示例中,当数据集大小从4更改为3时,组件会消失,但前3个项目的内部状态不会更改,因此前三个项目将被回收。

将所有状态移动到vuex将是​​一个可能的解决方案,但一些组件是通用的,我不希望它们包含有关vuex存储细节的知识。其实我对大多数组件使用vuex,但对于真正的通用组件,我不认为这是一个好的选择。

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"> 
 
\t <div>Prop: {{prop1}} || Internal state: {{internalState}}</div> 
 
</script>

回答

2

使用key

建议提供一键V型为尽可能 除非迭代DOM的内容很简单,或者你是故意 依靠对性能提升的默认行为。

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

更新fiddle

+0

谢谢@bertevans 此行为不应该是默认值。这是违反直觉的,可能导致隐藏的错误。 –

+0

@WilsonFreitas它的确会导致许多人旅行。 – Bert

相关问题