Vuejs/Nuxtjs watch 无法从 Vuex Store 观察对象数组中的变化
Vuejs/Nuxtjs watch is unable to watch for changes within the Array of Objects from Vuex Store
我正在开发一个应用程序,在此应用程序中使用 Vuejs/Nuxtjs
我有一个组件 IdentifiersNode.vue
,我想在其中监视 Vuex Store 数组 identifiersArray
.
我能够观察 identifiersArray
的直接更改,例如 push, direct key-value changes
但是当我向 identifiersArray
中的对象添加新对象时,watch
会由于某种原因无法工作。
以下是我的IdentifiersNode.vue
中的watch
函数:
watch: {
'$store.state.modules.identifiersInfoStore.identifiersArray': {
handler (val) {
console.log('WATCH : ' + JSON.stringify(val, null, 4))
},
deep: true
}
},
以下是 identifiersInfoStore .js
中 Vuex Store Mutations
中我的 identifiersArray
发生的变化:
saveIdentifiersInfo (state, payload) {
// Upon saving the Identifiers info save the information into respective object of identifiersArray
const identifiersNode = state.identifiersArray.find(node => node.identifiersId === state.currentNodeId)
console.log('NODE BEFORE : ' + JSON.stringify(identifiersNode, null, 4))
identifiersNode.instanceData = payload.instanceData
console.log('NODE ARRAY AFTER : ' + JSON.stringify(state.identifiersArray, null, 4))
},
正如我们所看到的,我正在向 identifiersArray
中的现有对象添加一个对象,但是当我这样做时,我希望我的 watch
函数在 IdentifiersNode.vue
中触发,因为我有 deep: true
但由于某种原因,它根本不起作用。
有人可以告诉我是否可以使用 Vuex store
和 Vue watch
检测数组的微小变化吗?如果不能,那么我可以采取什么替代方案?
以下是我来自 console.log 的 identifiersNode
:
NODE BEFORE : {
"identifiersId": 1,
"name": "identifiersNode1"
}
以下是来自 console.log 的 state.identifiersArray
:
NODE ARRAY AFTER : [
{
"identifiersId": 1,
"name": "identifiersNode1",
"instanceData": {
"name": "Batman",
"job":"IT"
}
}
]
如果您使用的是 vuex,我建议您使用 mapGetters
从商店中获取您的物品。每次您的项目更改时,这将自动监视值和 re-render。
这是文档:documentation
小例子
商店
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const state = {
data: ["Hello", "world"]
};
const mutations = {
addItem(state, item) {
state.data.push(item);
}
};
const getters = {
getData: (state) => state.data
};
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
组件
<template>
<div>
<h2>{{ data }}</h2>
<input type="text" v-model="inputValue" />
<button @click="addItemToStore">add item</button>
</div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
export default {
name: "HelloWorld",
computed: {
...mapGetters({
data: "getData",
}),
},
data: () => {
return {
inputValue: "",
};
},
methods: {
addItemToStore() {
this.addItem(this.inputValue);
this.inputValue = "";
},
...mapMutations({
addItem: "addItem",
}),
},
};
</script>
这里有一个codepen作为例子:https://codesandbox.io/s/vuex-store-forked-bl9rk0?file=/src/components/HelloWorld.vue
如果你想改变一个对象属性(或者在你的情况下将一个新对象添加到一个数组,它是你对象的属性)最好的办法是完全re-push当前对象。
例如,如果您有一个像 [{id: 1, values: [1,2,3]}, {id: 2, values: [4,5,6]}]
这样的数组,您可以使用 js splice method 更新值:
addValue(state, {id, valueToAdd}){
const pos = state.arr.findIndex(x => x.id === id)
if (pos !== -1){
const newObj = {...state.arr[pos]}
newObj.values.push(value)
state.arr.splice(pos, 1, newObj)
}
}
提供答案可能对以后的其他人有所帮助。
我实际上是将该对象附加到 Vuex Store 中 Array 中的现有对象。因此,手表无法识别变化。我将其更改为对我有用的 vue.set
。
以前我使用附加到我现有的对象:
identifiersNode.instanceData = payload.instanceData
后来我改成:
// Use the Vue reactive approach to add the instanceData object to existing object
Vue.set(identifiersNode, 'instanceData', payload.instanceData)
以下是我在 Vue 组件中的 watch,我在我的 mounted
中使用了这段代码,也可以在 watch 中使用:
// Watch for the changes on the identifiers array
this.$watch('$store.state.modules.identifiersInfoStore.identifiersArray', (val) => {
console.log(JSON.stringify(val,null,4))
}, { immediate: true, deep: true })
我正在开发一个应用程序,在此应用程序中使用 Vuejs/Nuxtjs
我有一个组件 IdentifiersNode.vue
,我想在其中监视 Vuex Store 数组 identifiersArray
.
我能够观察 identifiersArray
的直接更改,例如 push, direct key-value changes
但是当我向 identifiersArray
中的对象添加新对象时,watch
会由于某种原因无法工作。
以下是我的IdentifiersNode.vue
中的watch
函数:
watch: {
'$store.state.modules.identifiersInfoStore.identifiersArray': {
handler (val) {
console.log('WATCH : ' + JSON.stringify(val, null, 4))
},
deep: true
}
},
以下是 identifiersInfoStore .js
中 Vuex Store Mutations
中我的 identifiersArray
发生的变化:
saveIdentifiersInfo (state, payload) {
// Upon saving the Identifiers info save the information into respective object of identifiersArray
const identifiersNode = state.identifiersArray.find(node => node.identifiersId === state.currentNodeId)
console.log('NODE BEFORE : ' + JSON.stringify(identifiersNode, null, 4))
identifiersNode.instanceData = payload.instanceData
console.log('NODE ARRAY AFTER : ' + JSON.stringify(state.identifiersArray, null, 4))
},
正如我们所看到的,我正在向 identifiersArray
中的现有对象添加一个对象,但是当我这样做时,我希望我的 watch
函数在 IdentifiersNode.vue
中触发,因为我有 deep: true
但由于某种原因,它根本不起作用。
有人可以告诉我是否可以使用 Vuex store
和 Vue watch
检测数组的微小变化吗?如果不能,那么我可以采取什么替代方案?
以下是我来自 console.log 的 identifiersNode
:
NODE BEFORE : {
"identifiersId": 1,
"name": "identifiersNode1"
}
以下是来自 console.log 的 state.identifiersArray
:
NODE ARRAY AFTER : [
{
"identifiersId": 1,
"name": "identifiersNode1",
"instanceData": {
"name": "Batman",
"job":"IT"
}
}
]
如果您使用的是 vuex,我建议您使用 mapGetters
从商店中获取您的物品。每次您的项目更改时,这将自动监视值和 re-render。
这是文档:documentation
小例子
商店
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const state = {
data: ["Hello", "world"]
};
const mutations = {
addItem(state, item) {
state.data.push(item);
}
};
const getters = {
getData: (state) => state.data
};
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
组件
<template>
<div>
<h2>{{ data }}</h2>
<input type="text" v-model="inputValue" />
<button @click="addItemToStore">add item</button>
</div>
</template>
<script>
import { mapGetters, mapMutations } from "vuex";
export default {
name: "HelloWorld",
computed: {
...mapGetters({
data: "getData",
}),
},
data: () => {
return {
inputValue: "",
};
},
methods: {
addItemToStore() {
this.addItem(this.inputValue);
this.inputValue = "";
},
...mapMutations({
addItem: "addItem",
}),
},
};
</script>
这里有一个codepen作为例子:https://codesandbox.io/s/vuex-store-forked-bl9rk0?file=/src/components/HelloWorld.vue
如果你想改变一个对象属性(或者在你的情况下将一个新对象添加到一个数组,它是你对象的属性)最好的办法是完全re-push当前对象。
例如,如果您有一个像 [{id: 1, values: [1,2,3]}, {id: 2, values: [4,5,6]}]
这样的数组,您可以使用 js splice method 更新值:
addValue(state, {id, valueToAdd}){
const pos = state.arr.findIndex(x => x.id === id)
if (pos !== -1){
const newObj = {...state.arr[pos]}
newObj.values.push(value)
state.arr.splice(pos, 1, newObj)
}
}
提供答案可能对以后的其他人有所帮助。
我实际上是将该对象附加到 Vuex Store 中 Array 中的现有对象。因此,手表无法识别变化。我将其更改为对我有用的 vue.set
。
以前我使用附加到我现有的对象:
identifiersNode.instanceData = payload.instanceData
后来我改成:
// Use the Vue reactive approach to add the instanceData object to existing object
Vue.set(identifiersNode, 'instanceData', payload.instanceData)
以下是我在 Vue 组件中的 watch,我在我的 mounted
中使用了这段代码,也可以在 watch 中使用:
// Watch for the changes on the identifiers array
this.$watch('$store.state.modules.identifiersInfoStore.identifiersArray', (val) => {
console.log(JSON.stringify(val,null,4))
}, { immediate: true, deep: true })