在其他所有的问题中,我都能找到数据被使用,防止反应性。这里的数据没有被使用,道具本身在渲染中没有更新。
我的VueX函数是
addItemColumn()
在第一个盒子里创建一个新的列,本质上盒子不允许自己成长;但是,父代可以要求添加一个新的列(到第一个盒子里)。
MoveBoxDown()
应该是不言自明的,但会将当前的方框(该函数被调用)与下面的方框进行切换。
下面是发生了什么...
当只执行 item 列时,一个带有默认项目的额外列被正确添加并重新渲染。然而,当首先执行moveBoxDown时,发生的情况是盒子正确切换并重新渲染,但当我去执行addItemColumn时,子项目Box没有看到任何更新。
奇怪的是,1) addItemColumn()
作品和演绎2) moveBoxDown()
作品和演绎
所以不会出现更新moveBoxDown失败传播导致addItemColumn的问题。事实上,运行 moveBoxDown()
与我的任何其他突变完美地工作。
3) Vue Devtools显示Box已经更新,对于这个问题 box.items
更新4) 根据示例代码 <p>{{ box.items.length }}<p>
的更新,而不是子代的Box。
如果它在父代中不起作用,我可能会认为是子代的键入问题;然而,它确实如此,并且结合devtools正确显示更新的 box
在我看来,由于某种未知的原因,子代似乎没有检测到道具已被更新?
我能想到的唯一的解决方法是把Box变成一个有槽的组件,因为父体是知道的,这似乎可以缓解这个问题。
我在VueX中拥有以下数据结构
Boxes = [
{
id: number
items: [
{
id: number
properties: {
...
}
},
...
]
},
...
]
一个项目正在被添加使用 .push()
在VueX中,由 addBox
这样就能检测到变化。同样,在一般情况下,这样做是可行的,但也有拒绝更新的情况,即使Vue开发工具显示了正确的,现在更新的道具值。
父级
<template>
<b-button @click="addBox()">Add Box</b-button>
<div v-for="(box, index) in boxes" :key="`box_${index}`">
<!-- This updates so is not related to the parents loop -->
<p>{{ box.items.length }}</p>
<Box :box="box" />
</div>
</template>
<script>
// Import VueX
import { mapGetters, mapActions } from "vuex";
// Import Components
import Box from "~/components/Box";
export default {
name: "BoxesPage",
layout: "BoxesLayout",
components: { Box },
computed: {
...mapGetters({
boxes: "items/boxes"
})
},
methods: {
...mapActions({
addItemColumn: "items/addItemColumn"
})
},
async fetch({ store, params }) {
await store.dispatch("items/getInventory");
}
};
</script>
盒子
<template>
<div>
<!-- Neither of these update either, so this is not related to the child's loop -->
<p>{{ box }}<p>
<p>{{ box.items.length }}<p>
<b-button
@click="moveBoxDown()"
icon-right="chevron-down"
/>
<div
v-for="item in box.items"
:key="
`box_${box.index}_item_${item.index}_${item.name}`"
>
<!-- This does not add a new item -->
<Item :item="item" />
</div>
</div>
</template>
<script>
// Import VueX
import { mapGetters, mapActions } from "vuex";
// Import Components
import Item from "~/components/Item";
export default {
name: "Box",
components: { Item },
props: {
Box: {
type: Object,
required: true
}
},
methods: {
...mapActions({
moveBoxDown: "items/moveBoxDown",
})
}
};
</script>
我不会附上VueX的行文,因为VueX的实现似乎又是完全没有问题的......不管它是否正确地重新渲染,Vue开发工具都显示该道具被正确地更新了。
编辑:VueX" items.js"
export const state = () => ({
boxes: []
});
export const actions = {
moveFrameDown({ commit }, frameIndex) {
commit('switchBoxes', { fromIndex: frameIndex, toIndex: frameIndex + 1 });
},
addBoxColumn({ commit }, item) {
// Item is a default item type
commit('newItemColumn', item);
},
}
export const mutations = {
SwitchBoxes: (state, { fromIndex, toIndex }) => {
state.boxes[fromIndex] = {
index: fromIndex,
items: state.boxes.splice(toIndex, 1, {
index: toIndex,
items: state.frames[fromIndex].items
})[0].items
};
},
newItemColumn: (state, itemProps) => {
state.boxes[0].items.push({
id: state.idCounter
props: itemProps
});
state.idCounter += 1;
}
};
你的例子不是很简陋,所以我只能猜测可能是什么原因。
这是个危险的信号。
state.boxes[fromIndex] = { ... }
从... 文件:
Vue无法检测到以下对数组的更改。
- 当你 直接设置一个索引的项目,例如
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,比如说。
vm.items.length = newLength
你也在做一个 splice()
数组上,Vue可以检测到,所以恰好数组的变化可能会反映在视图中,然而你可能没有意识到的是,你分配给数组索引的新对象不会被反应。
你需要使用 Vue.set()
:
Vue.set(state.boxes, fromIndex, { ... })