删除数据中的元素不会刷新 VueJS 中的键
Remove element in data doesn't refresh keys in VueJS
我正在尝试制作一个提供输入和颜色选择器的项目列表。它应该始终在列表末尾有一个空元素。
元素由存储在 data
中的对象填充。
一切正常,我做了一个简单的方法过滤空值的对象,然后添加一个新的。
但是,当用户在不是最后一个的元素上设置空值时:
- “数据”值有序,空值已删除
- 但是视图保留了“键”,所以元素仍然在这里
这是我在父 Vue 上所做的:
addEmptyElement() {
// now find any empty values
this.values = this.values.filter((v) => v.length);
// and append an empty one
this.values.push("");
},
并且这些值用于绑定 Item 组件,如下所示:
<Item
v-for="(v, i) in values"
:key="i"
v-bind:text="v"
@valueChanged="onItemChanged"
/>
“valueChanged”事件由 Item 发出并提供列表中的位置和更改的值。
我创建了一个更简单的示例,您可以在此处查看:
https://codesandbox.io/s/vue-component-order-problem-rc4o1?file=/src/App.vue
给出一些精确度:
- “Element”组件“emit”值发生变化,因此父级知道哪个元素发生了变化
- 我使用
this.$.vnode.key
在父 vue 中找到要更改的值(这可能是有问题的地方)
也许我做错了,执行不好,所以请告诉我我做错了什么:)
谢谢!
我觉得你看到的和documentation
中的这段比较有关系
When Vue is updating a list of elements rendered with v-for
, by default it uses an "in-place patch" strategy. If the order of the data items has changed, instead of moving the DOM elements to match the order of the items, Vue will patch each element in-place and make sure it reflects what should be rendered at that particular index.
This default mode is efficient, but only suitable when your list render output does not rely on child component state or temporary DOM state (e.g. form input values).
这就是为什么在 v-for
中使用简单的 index 作为 key
是棘手的。最好不要依赖索引并维护自己的唯一性 id
即使它需要更多工作...
this.$.vnode.key
的用法也有异味...它没有记录在案 API 所以你绝对应该避免它,只需通过道具明确地传递 id
...其他想法
就在我发布我的答案之后,我又意识到一件事......所以只是为了完整:
这可以很容易地与 v-for
index
作为键一起使用。它对您不起作用的原因在于您的 <Item>
组件。您将 text
道具传递给 Item 组件。您使用 prop 的值 一次性初始化 value
在 data
中使用 value
作为 v-model
input
.
重新呈现列表时会发生什么? Vue 为列表中的每个项目更新 text
属性,但是更新 对用作 v-model
的内部组件的 value
没有影响(所以它对 <input>
元素中显示的值没有影响)!!
解决方法是重写Item
组件:
<template>
<div>
<input type="text" v-model="model" />
</div>
</template>
<script>
export default {
props: ["modelValue"],
computed: {
model: {
get() {
return this.modelValue;
},
set(evt) {
this.$emit("update:modelValue", evt);
},
},
},
};
</script>
...并更改 App.vue
:
<Item
v-for="(v, i) in values"
:key="i"
:modelValue="v"
@update:modelValue="onItemChanged(i, $event)"
/>
它 正常工作 其余代码不变 - 2nd example
我正在尝试制作一个提供输入和颜色选择器的项目列表。它应该始终在列表末尾有一个空元素。
元素由存储在 data
中的对象填充。
一切正常,我做了一个简单的方法过滤空值的对象,然后添加一个新的。
但是,当用户在不是最后一个的元素上设置空值时:
- “数据”值有序,空值已删除
- 但是视图保留了“键”,所以元素仍然在这里
这是我在父 Vue 上所做的:
addEmptyElement() {
// now find any empty values
this.values = this.values.filter((v) => v.length);
// and append an empty one
this.values.push("");
},
并且这些值用于绑定 Item 组件,如下所示:
<Item
v-for="(v, i) in values"
:key="i"
v-bind:text="v"
@valueChanged="onItemChanged"
/>
“valueChanged”事件由 Item 发出并提供列表中的位置和更改的值。
我创建了一个更简单的示例,您可以在此处查看:
https://codesandbox.io/s/vue-component-order-problem-rc4o1?file=/src/App.vue
给出一些精确度:
- “Element”组件“emit”值发生变化,因此父级知道哪个元素发生了变化
- 我使用
this.$.vnode.key
在父 vue 中找到要更改的值(这可能是有问题的地方)
也许我做错了,执行不好,所以请告诉我我做错了什么:)
谢谢!
我觉得你看到的和documentation
中的这段比较有关系When Vue is updating a list of elements rendered with
v-for
, by default it uses an "in-place patch" strategy. If the order of the data items has changed, instead of moving the DOM elements to match the order of the items, Vue will patch each element in-place and make sure it reflects what should be rendered at that particular index.
This default mode is efficient, but only suitable when your list render output does not rely on child component state or temporary DOM state (e.g. form input values).
这就是为什么在 v-for
中使用简单的 index 作为 key
是棘手的。最好不要依赖索引并维护自己的唯一性 id
即使它需要更多工作...
this.$.vnode.key
的用法也有异味...它没有记录在案 API 所以你绝对应该避免它,只需通过道具明确地传递 id
...其他想法
就在我发布我的答案之后,我又意识到一件事......所以只是为了完整:
这可以很容易地与 v-for
index
作为键一起使用。它对您不起作用的原因在于您的 <Item>
组件。您将 text
道具传递给 Item 组件。您使用 prop 的值 一次性初始化 value
在 data
中使用 value
作为 v-model
input
.
重新呈现列表时会发生什么? Vue 为列表中的每个项目更新 text
属性,但是更新 对用作 v-model
的内部组件的 value
没有影响(所以它对 <input>
元素中显示的值没有影响)!!
解决方法是重写Item
组件:
<template>
<div>
<input type="text" v-model="model" />
</div>
</template>
<script>
export default {
props: ["modelValue"],
computed: {
model: {
get() {
return this.modelValue;
},
set(evt) {
this.$emit("update:modelValue", evt);
},
},
},
};
</script>
...并更改 App.vue
:
<Item
v-for="(v, i) in values"
:key="i"
:modelValue="v"
@update:modelValue="onItemChanged(i, $event)"
/>
它 正常工作 其余代码不变 - 2nd example