问题描述
我在vuex存储区中有一个带有表[t1,t2]的列表,当更新t1时,我必须更改表数组才能更新t1。
对于每个表,我使用<Table v-for="(item,index) in tables" :key="index" :data="item">
,其中它使用Table.vue。在Table.Vue中,我有:
props: {
data: {
type: Object,default: null
}
},
但是,当t1更改时,它也将强制更新到t2,这是可以理解的,因为存储中的整个“ tables”变量都发生了变异。但是我只希望组件在道具发生实际变化时进行更新,以免t2不必要地更新。我试图研究记忆,我之前在React-projects中使用它来解决这个问题。我真的没有发现任何易于使用的东西,并且搜索“ memoization vuejs”并没有真正让我继续前进。
我如何在vuex存储中进行突变以对表进行突变:
my_mutation(state,data) {
let newList = [...state.tables];
let index = newList.findindex(i => i.tableName === data.tableName);
if (index !== -1) {
newList[index] = data.value;
}
Vue.set(state,'currentViews',newList);
}
如您所见,该代码当时仅在state.tables中变异1个元素,但设置整个表变量。这将导致update()函数在组件中触发(注意,不是created(),因为这仅在我获取并填充表变量时才发生)并重新释放组件。
由于在发生突变时未触发created(),因此这告诉我该组件仍然存在并且不需要重新创建。这里的目标不是在道具没有更改时触发update()并防止重新渲染该特定组件。
解决方法
您可能应该添加一些代码,因为您看到的内容似乎很奇怪...
看下面的例子(更新的例子使用Vuex ...只是为了确定)
- 第一个按钮更改索引1处第一个表的数据。结果 =仅第一个组件重新呈现
- 第二个按钮完全替换第二个表的数据。 结果 =仅重新提交第二个组件
- 第三个按钮用一个新数组替换整个
tables
数组。 结果 =两个组件的重新渲染(符合预期) - 好奇者的第四个按钮;)...由现有实例组成的全新
tables
数组。 结果 =完全不重新渲染 - 第五个按钮(Q更新后添加)
- 与上述问题相同的更新方式
- 结果-仅第二张表退回!与您所说的明显矛盾...
- 请注意,如果您从一开始就在
currentViews
中拥有state
属性,则无需使用Vue.set
-简单的分配就足够了
更新:在updated
组件中添加了带有console.log
的{{1}}钩子,以检查日志是否与表标题中的时间变化相关-已确认
mytable
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
tables: [
['item 1','item 2'],['item 1','item 2']
]
},mutations: {
mutate1st(state) {
Vue.set(state.tables[0],state.tables[0][0]+'+1')
},mutateTables(state) {
Vue.set(state.tables,1,['item 3','item 4'])
},replaceTables(state) {
state.tables = [
['item 1','item 2']
]
},newArrayCreatedFromPreviousOnes(state) {
state.tables = [...state.tables] // we are creating new array composed from existing instances
},sameWayAsInQuestion(state) {
let newList = [...state.tables];
newList[1] = ['item 5','item 6'];
Vue.set(state,'tables',newList);
}
}
})
const mytable = Vue.component('mytable',{
props: ['title','data'],template: `
<div>
<div> {{ title }} ({{ now() }}) </div>
<div v-for="(item,index) in data" :key="index">{{ item }}</div>
<hr>
</div>
`,methods: {
now() {
const date = new Date();
return date.toLocaleTimeString();
}
},updated() {
console.log(`${this.title} updated at ${this.now()}`)
}
})
const app = new Vue({
store,components: { mytable },template: `
<div>
<button @click="mutate1st">Mutate 1st table data</button>
<button @click="mutateTables">Mutate tables array</button>
<button @click="replaceTables">Replace tables array</button>
<button @click="newArrayCreatedFromPreviousOnes">Just for curiosity...</button>
<button @click="sameWayAsInQuestion">Same way as in question</button>
<hr>
<mytable v-for="(table,index) in $store.state.tables" :key="index" :title="'Table ' + index" :data="table" />
</div>
`,methods: {
...Vuex.mapMutations(['mutate1st','mutateTables','replaceTables','newArrayCreatedFromPreviousOnes','sameWayAsInQuestion'])
}
})
app.$mount("#app")
,
更新:我在Table.vue中还有另一个组件,该组件依赖于存储变量,该存储变量在更改t1时发生了突变,导致其余表发生更改。每日提示:检查所有嵌套组件是否不依赖于受更改影响的某些存储变量