1. 使用 Vue.mixin
结合 Object.freeze
- 解决方案:在项目入口处定义一个
mixin
,对 Vuex
中获取的状态数据进行冻结。例如:
import Vue from 'vue';
Vue.mixin({
created() {
const store = this.$store;
Object.keys(store.state).forEach(key => {
Object.freeze(store.state[key]);
});
}
});
- 原理:
Object.freeze
方法可以冻结一个对象,使得对象的属性不能被修改、添加或删除。Vue 的计算属性依赖于数据的响应式变化,当数据冻结后,Vue 检测不到数据变化,从而减少不必要的重新计算,同时由于 Vuex
状态修改是通过 mutation
进行,依然可以保证数据一致性。
2. 利用 Vuex
的 getter
缓存
- 解决方案:将计算属性逻辑转移到
Vuex
的 getter
中。getter
会自动缓存,只有在它依赖的状态发生改变时才会重新计算。例如:
// store.js
const store = new Vuex.Store({
state: {
list: [1, 2, 3, 4, 5]
},
getters: {
filteredList: state => {
return state.list.filter(item => item > 3);
}
}
});
// 组件中
<template>
<div>
<ul>
<li v-for="item in filteredList" :key="item">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
computed: {
filteredList() {
return this.$store.getters.filteredList;
}
}
};
</script>
- 原理:
Vuex
的 getter
内部实现了类似缓存机制,它会记住最后一次的计算结果,当依赖的 state
没有变化时,直接返回缓存结果,避免重复计算。
3. 使用 watch
结合手动控制计算
- 解决方案:在组件中使用
watch
监听 Vuex
状态的变化,当状态变化时,手动控制计算属性的计算时机。例如:
<template>
<div>
<p>{{ computedValue }}</p>
</div>
</template>
<script>
export default {
data() {
return {
tempValue: null
};
},
computed: {
computedValue() {
return this.tempValue;
}
},
watch: {
'$store.state.someState'(newValue) {
// 这里进行复杂计算
this.tempValue = newValue * 2;
}
}
};
</script>
- 原理:
watch
可以精确监听 Vuex
状态的变化,只有在监听的状态变化时才进行计算,并更新相关数据,避免计算属性因依赖多个状态频繁重新计算,同时通过手动赋值保证数据一致性。
4. 拆分计算属性
- 解决方案:将复杂的计算属性拆分成多个简单的计算属性,每个计算属性只依赖于少量的
Vuex
状态。例如,原计算属性依赖 state.a
,state.b
,state.c
,可拆分为三个计算属性,分别依赖 state.a
,state.b
,state.c
,然后在最终使用时再进行组合。
<template>
<div>
<p>{{ combinedValue }}</p>
</div>
</template>
<script>
export default {
computed: {
valueA() {
return this.$store.state.a * 2;
},
valueB() {
return this.$store.state.b + 1;
},
valueC() {
return this.$store.state.c - 5;
},
combinedValue() {
return this.valueA + this.valueB + this.valueC;
}
}
};
</script>
- 原理:Vue 的计算属性是基于依赖进行缓存的,拆分后每个计算属性依赖变少,重新计算频率降低,而且当某个依赖状态变化时,只影响相关的计算属性,不影响其他部分,保证数据一致性的同时减少不必要计算。