Vue.js 基础数据更改时重用组件内部状态
Vue.js components internal state being reused when underlying data changes
我正在开发一个基于 vue.js 的中型 Web 应用程序。我一直面临几个主要与 vue 实例生命周期相关的虚拟 DOM 问题。
以下代码片段(jsFiddle 也可用 here)演示了其中的一些问题。 test-component vue 组件接收一个 属性 值并使用该值更新其内部状态。
只要数据集发生变化(通过排序或通过新数据),属性就会更新,但内部状态不会。通过 运行 代码片段并单击按钮很容易看到这一点。
我知道 data 组件属性是一个函数,它看起来只有在创建组件时才会被调用。这种解释是怎么回事。问题是我不知道如何实现预期的行为,即:只要数据源发生变化,所有子组件的内部状态都会更新。
- 是否有组件生命周期回调
"refreshed"?我想要一个组件刷新回调。我需要单独观察道具变化吗?那会很难看。
- 当 props 改变时,是否有一种干净的方法来更新内部状态?
- 是否可以销毁所有子组件并强制重新创建它们?我知道这不是最好的选择,但它可以解决我所有的数据绑定问题:)
- 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">
<div>Prop: {{prop1}} || Internal state: {{internalState}}</div>
</script>
使用 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>
已更新 fiddle。
我正在开发一个基于 vue.js 的中型 Web 应用程序。我一直面临几个主要与 vue 实例生命周期相关的虚拟 DOM 问题。
以下代码片段(jsFiddle 也可用 here)演示了其中的一些问题。 test-component vue 组件接收一个 属性 值并使用该值更新其内部状态。
只要数据集发生变化(通过排序或通过新数据),属性就会更新,但内部状态不会。通过 运行 代码片段并单击按钮很容易看到这一点。
我知道 data 组件属性是一个函数,它看起来只有在创建组件时才会被调用。这种解释是怎么回事。问题是我不知道如何实现预期的行为,即:只要数据源发生变化,所有子组件的内部状态都会更新。
- 是否有组件生命周期回调
"refreshed"?我想要一个组件刷新回调。我需要单独观察道具变化吗?那会很难看。 - 当 props 改变时,是否有一种干净的方法来更新内部状态?
- 是否可以销毁所有子组件并强制重新创建它们?我知道这不是最好的选择,但它可以解决我所有的数据绑定问题:)
- 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">
<div>Prop: {{prop1}} || Internal state: {{internalState}}</div>
</script>
使用 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>
已更新 fiddle。