Vue 更改为数组而不更新 DOM
Vue changes to array not updating the DOM
我正在尝试更改通过 Props 传递给子组件的父组件中的数组(插入和更新数据),但是 DOM 没有被更新。
父组件:
<UsersList
v-for="(role, i) in userRolesNames"
:key="i"
:users="usersPages[i].data"
/>
子组件:
<template>
<div
v-for="user in users"
:key="user.id"
>
<span>{{ user.name }}</span>
<div>
<i
class="bi bi-pen-fill edit-icon m-pointer"
@click="onClickEdit(user)"
></i>
<i
class="bi bi-trash-fill delete-icon ms-2 m-pointer"
@click="onClickDelete(user)"
></i>
</div>
</div>
</template>
<script lang="ts">
// recieving the array
props: {
users: {
required: true,
type: Array as PropType<usersType[]>
}
}
</script>
每个用户基本结构如下:
{
id: x,
name: 'x',
email: 'x',
login: 'x',
role: x
}
问题是当尝试在 usersPages[i].data 数组中插入或更新记录时,DOM 没有改变。如果我使用 Vue 开发人员工具,数据会正确更改,但 DOM 不是。
尝试在数组上使用 push 方法插入但没有成功。唯一有用的是:
const newUser = response.data;
const page = this.usersPages[newUser.role - 1];
Vue.set(page, 'data', [...page.data, newUser]);
要更新,我尝试直接更改用户属性,但像插入一样,DOM 不会更新。有效的是:
const page = this.usersPages[user.role - 1];
const oldUsers = page.data.filter(u => u.id != user.id);
Vue.set(page, 'data', [ ...oldUsers, response.data ]);
有效但看起来不对...有人可以帮忙吗?
我之前遇到过类似的问题。我相信这是 vue 中的一个错误。原因是 Vue 已经渲染了 v-for
。 Vue 目前还不知道如何处理数组中的变化。作为解决方法,我所做的是将脚本中的 updateKey
变量设置为 0。然后在每次更新数组 updateKey++
时递增此变量。我们将此密钥用于我们的组件。
在子组件上,
<template>
<span
v-for="user in users"
:key="user.id"
>
<div :key="updateKey">
<span>{{ user.name }}</span>
<div>
<I
class="bi bi-pen-fill edit-icon m-pointer"
@click="onClickEdit(user)"
></i>
<I
class="bi bi-trash-fill delete-icon ms-2 m-pointer"
@click="onClickDelete(user)"
></i>
</div>
</div>
</span>
</template>
和onClickEdit(user)
和onClickDelete(user)
确保你有updateKey++
DOM 不会更新,因为您没有进行被动更新。要反应性地更新此值,您应该监听一些事件(例如 input
),您将在子组件中发出该事件并将新的(!)值传递给您的 属性。但更好的方法是通过 v-model
.
绑定你的组件
P.S。 - 所以你可以看到 devtools 的变化,因为这不是 Vue 生命周期的一部分,它就像一个观察实际数据的解析器,但没有上下文。
我决定创建一个示例来向@peperoneen 展示我是如何做到的,因为我相信这种方法是正确的。但在示例本身中,它有效,而在我的项目中,它没有,唯一的区别是列表最初填充的方式。
为了加载用户,我向 API 请求返回分页数据,我通常使用“=”运算符分配这些数据。但是,我决定逐步进行分配,在用户部分,我使用了 'push' 方法。这样,使用 push 和 filter 的列表操作正常工作,更新 DOM 而无需使用 Vue.set
我认为问题出在生成列表的方式上。我想我并没有被动地这样做...
我正在尝试更改通过 Props 传递给子组件的父组件中的数组(插入和更新数据),但是 DOM 没有被更新。
父组件:
<UsersList
v-for="(role, i) in userRolesNames"
:key="i"
:users="usersPages[i].data"
/>
子组件:
<template>
<div
v-for="user in users"
:key="user.id"
>
<span>{{ user.name }}</span>
<div>
<i
class="bi bi-pen-fill edit-icon m-pointer"
@click="onClickEdit(user)"
></i>
<i
class="bi bi-trash-fill delete-icon ms-2 m-pointer"
@click="onClickDelete(user)"
></i>
</div>
</div>
</template>
<script lang="ts">
// recieving the array
props: {
users: {
required: true,
type: Array as PropType<usersType[]>
}
}
</script>
每个用户基本结构如下:
{
id: x,
name: 'x',
email: 'x',
login: 'x',
role: x
}
问题是当尝试在 usersPages[i].data 数组中插入或更新记录时,DOM 没有改变。如果我使用 Vue 开发人员工具,数据会正确更改,但 DOM 不是。
尝试在数组上使用 push 方法插入但没有成功。唯一有用的是:
const newUser = response.data;
const page = this.usersPages[newUser.role - 1];
Vue.set(page, 'data', [...page.data, newUser]);
要更新,我尝试直接更改用户属性,但像插入一样,DOM 不会更新。有效的是:
const page = this.usersPages[user.role - 1];
const oldUsers = page.data.filter(u => u.id != user.id);
Vue.set(page, 'data', [ ...oldUsers, response.data ]);
有效但看起来不对...有人可以帮忙吗?
我之前遇到过类似的问题。我相信这是 vue 中的一个错误。原因是 Vue 已经渲染了 v-for
。 Vue 目前还不知道如何处理数组中的变化。作为解决方法,我所做的是将脚本中的 updateKey
变量设置为 0。然后在每次更新数组 updateKey++
时递增此变量。我们将此密钥用于我们的组件。
在子组件上,
<template>
<span
v-for="user in users"
:key="user.id"
>
<div :key="updateKey">
<span>{{ user.name }}</span>
<div>
<I
class="bi bi-pen-fill edit-icon m-pointer"
@click="onClickEdit(user)"
></i>
<I
class="bi bi-trash-fill delete-icon ms-2 m-pointer"
@click="onClickDelete(user)"
></i>
</div>
</div>
</span>
</template>
和onClickEdit(user)
和onClickDelete(user)
确保你有updateKey++
DOM 不会更新,因为您没有进行被动更新。要反应性地更新此值,您应该监听一些事件(例如 input
),您将在子组件中发出该事件并将新的(!)值传递给您的 属性。但更好的方法是通过 v-model
.
P.S。 - 所以你可以看到 devtools 的变化,因为这不是 Vue 生命周期的一部分,它就像一个观察实际数据的解析器,但没有上下文。
我决定创建一个示例来向@peperoneen 展示我是如何做到的,因为我相信这种方法是正确的。但在示例本身中,它有效,而在我的项目中,它没有,唯一的区别是列表最初填充的方式。
为了加载用户,我向 API 请求返回分页数据,我通常使用“=”运算符分配这些数据。但是,我决定逐步进行分配,在用户部分,我使用了 'push' 方法。这样,使用 push 和 filter 的列表操作正常工作,更新 DOM 而无需使用 Vue.set
我认为问题出在生成列表的方式上。我想我并没有被动地这样做...