Vue.js Vuex:向对象添加动态属性,而不触发现有属性上的观察程序
我有一个带有对象的Vuex存储:Vue.js Vuex:向对象添加动态属性,而不触发现有属性上的观察程序,vue.js,vuex,Vue.js,Vuex,我有一个带有对象的Vuex存储: state: { contents: {}, } 其中,我按键动态存储内容: mutations: { updateContent: (state, { id, a, b }) => { Vue.set(state.contents, id, { a, b }); }, } 并让他们使用: getters: { content: (state) => (id) => { if (
state: {
contents: {},
}
其中,我按键动态存储内容:
mutations: {
updateContent: (state, { id, a, b }) => {
Vue.set(state.contents, id, { a, b });
},
}
并让他们使用:
getters: {
content: (state) => (id) => {
if (id in state.contents) return state.contents[id];
return [];
}
},
假设我有这样一个组件:
export default {
props: ["id"],
computed: {
myContent() {
return this.$store.getters.content(this.id)
}
},
// ...
}
如何使用变异添加动态属性而不触发组件中的更改?查看state.contents的未更改、已存在的属性
另请参见此图。如果您想查看对象的内部属性,可以使用
深度观察程序
在您的情况下,我假设您正确设置了getter、setter和update方法。您应该将此添加到您的观察者:
// ...
watch:{
id: {
deep: true,
handler(newVal, oldVal){
console.log("New value and old value: ", newVal, oldVal")
// ... make your own logic here
}
}
}
让我再解释一下上面的代码,当我们想查看Vue中任何对象的内部属性时,我们应该使用deep
和handler
函数来处理每次更改。(请记住,handler不是一个随机名称,它是保留关键字)我试图通过检查fiddle:,来找出它,我有一个可能的原因导致这种行为
当观察到的对象或其中的属性发生更改时,将更新或访问getter和计算属性。在这种情况下,content
getter正在“监视”state.contents
store属性,因此每次更新store.contents
时,调用content
getter,然后调用计算属性myContent()
更新其值,并使用this.update++
增加updated
数据属性
因此,如果更新了state.contents
属性,组件将始终更新,即添加一个新的不相关属性
,Vue(x)似乎无法做到这一点。但是,通过添加一个空的观察者(是的,这是一种攻击),您可以使Vue组件暂时不起作用(基于此)
基本上,我们在对象本身上有一个观察者,在每个属性上都有一个观察者。我们将摧毁目标上的观察者。这样做时,我们必须确保,当一个组件第一次调用getter时,它返回一个被动值,而不是{}
,因为getter无法再观察到向对象添加新属性的情况。因此,我们在初始化对象时添加了一个touch
。此函数需要对象的原始观察者在其属性上创建观察者,从而对组件进行一次(但仅一次)不必要的更新:
mutations: {
updateContent: (state, { id, a, b }) => {
Vue.set(state.contents, id, { a, b });
},
touch: (state, { id }) => {
if(id in state.contents) return
if (myObserver === null)
myObserver = state.contents.__ob__
state.contents.__ob__ = myObserver
Vue.set(state.contents, id, {});
state.contents.__ob__ = new Observer({});
}
},
可以使用以下方法获得构造函数:
const Observer = (new Vue()).$data.__ob__.constructor;
每当id
更改时,我们的组件必须调用touch
:
props: ["id"],
watch: {
i: {
immediate: true,
handler() {
this.$store.commit("touch", { id: this.id })
}
}
},
computed: {
myContent() {
return this.$store.getters.content(this.id)
}
},
如中所示,向对象添加新属性不会再触发不必要的更新。可以使用全局事件总线而不是vuex getter:
const eventBus = new Vue();
组件可以订阅所需的元素:
watch: {
id: {
handler(n, o) {
if (o) eventBus.$off(o + "", this.onChange);
eventBus.$on(n + "", this.onChange);
this.$store.dispatch("request", { id: n });
},
immediate: true
}
},
必须通知组件的更改将使用操作进行调度:
actions: {
request(_, { id }) {
eventBus.$emit(id + "", this.getters.content(id));
},
updateContent({ commit }, { id, a, b }) {
commit("updateContent", { id, a, b });
eventBus.$emit(id + "", { a, b });
}
}
这样可以精确地控制何时触发更新
.理论上,这是阻止设置程序,但您也可以只制作一个只监视此属性的计算程序,并将其从vue e外部添加到冻结的对象中。这并不能解决问题。我不觉得没有调用处理程序有什么问题-调用太频繁了。