vue.js - Vue子组件道具未更新
问题描述
在所有其他问题中,我发现数据被用于防止反应。这里没有使用数据,道具本身无法在渲染中更新。
我的 VueX 功能是:
addItemColumn()
在第一个 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。
如果它在父母身上不起作用,我可能会认为这对孩子来说是一个关键问题;但是,它确实并结合 devtools 正确显示了box
孩子的更新,在我看来,出于某种未知原因,孩子没有检测到道具已更新?
我能想到解决这个问题的唯一方法是将 Box 变成一个开槽组件,因为父级知道,这似乎可以缓解这个问题。
我在 VueX 中有以下数据结构
Boxes = [
{
id: number
items: [
{
id: number
properties: {
...
}
},
...
]
},
...
]
.push()
在 VueX中正在添加一个项目,由addBox
因此检测到更改触发。同样,一般来说这是可行的,但在某些情况下,即使 Vue 开发工具显示正确的、现已更新的 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>
盒子
<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, { ... })
推荐阅读
- powershell - 共享文件区 - 如何改进我的 PowerShell 脚本?
- c++ - 当返回类型是向量容器时,是否有在 c++ 中返回 Null 的解决方法?
- javascript - 读取路线参数 Angular
- matlab - 将 if/else 语句转换为允许多个选择的代码
- getstream-io - 可以丰富集合中的数据吗?
- c++ - C++ 自定义类继承 Eigen 初始值设定项列表
- reactjs - 知道 React 中的 CanvasRenderingContext2D 的人,请帮助:)
- jquery - 如何为仅触发一次的多个事件添加事件侦听器?
- sockets - 无法从现有 UDP 套接字绑定 UDT 套接字
- shell - 从文件中删除数据的 Ansible 任务