在所有其他问题中,我都能发现正在使用数据来防止反应。这里没有使用数据,道具本身无法在渲染中更新。
我的VueX函数是:
addItemColumn()
在第一个Box中创建一个新列,从本质上讲,这些Box不允许自己增长;但是,父级可以请求将新列添加到(在第一个框中。)
MoveBoxDown()
应该是不言自明的,但是将当前框(调用此功能的框)切换为下面的框。
这就是发生的事情...
仅执行项目列时,将正确添加并重新渲染具有默认项目的其他列。但是,当首先执行moveBoxDown时,发生的情况是框正确切换并重新渲染,但是当我执行addItemColumn时,子Box看不到Box的任何更新。
奇怪的是
1)addItemColumn()
可以工作并渲染
2)moveBoxDown()
可以工作并渲染
因此,更新moveBoxDown传播似乎不会失败,从而导致addItemColumn问题。事实上,将moveBoxDown()
与我的任何其他突变一起运行都是完美的。
3)Vue Devtools显示Box已更新,因此box.items
已更新
4)按照示例代码<p>{{ box.items.length }}<p>
在父Box(而不是子Box)中更新。
如果它在父母中不起作用,我可能会认为这是孩子的关键问题。但是,它确实结合了devtools并正确地向孩子显示了更新的box
,在我看来,出于某种未知的原因,我没有发现孩子没有检测到道具已更新?
我想解决此问题的唯一方法是将Box变成插槽组件,因为家长知道了,这似乎可以缓解问题。
我在VueX中具有以下数据结构
Boxes = [
{
id: number
items: [
{
id: number
properties: {
...
}
},
...
]
},
...
]
正在.push()
触发的情况下在VueX中使用addBox
添加项目,因此可以检测到更改。再次,一般来说,这是可行的,但是在某些情况下,即使Vue Dev工具显示正确的,现在已更新的prop值,它也拒绝更新。
父母
<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>
Box
<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;
}
};
答案 0 :(得分:3)
您的示例不是非常少,所以我只能猜测可能是什么原因。
这是一个危险信号:
state.boxes[fromIndex] = { ... }
来自docs:
Vue无法检测到对数组的以下更改:
- 当您直接设置带有索引的项目时,例如
vm.items[indexOfItem] = newValue
- 修改数组的长度时,例如
vm.items.length = newLength
您还同时在数组上执行了splice()
,Vue可以检测到它,因此巧合的是,数组更改很可能会反映在视图中,但是您可能没有意识到的是新对象您分配给数组索引的对象将是无反应的。
您需要使用Vue.set()
:
Vue.set(state.boxes, fromIndex, { ... })