Vue 3 使用代理包装器比较对相同对象的引用

pad*_*van 1 vue.js vue-component vuejs2 vuejs3

我有父/子组件,并通过代理和不使用代理绑定对象数组:

const selectedTags = ref([]);
const tags = [
    {
        id: 'efrwe',
    },
    {
        id: 'dhjhe23',
    }];

<Child :tags="tags" :selectedTags="selectedTags">
Run Code Online (Sandbox Code Playgroud)

在子组件中,我将选定的元素从“tags”添加到“selectedTags”,它对源数组中的对象的引用!

props.selectedTags.push(tags[0]);
Run Code Online (Sandbox Code Playgroud)

但后来我尝试比较同一个对象上的这个引用,我返回 false!

console.log(tags[0] == selectedTags[0]); // false
Run Code Online (Sandbox Code Playgroud)

你说“好吧,你尝试比较代理对象和清除对象”,但我尝试与代理目标进行比较并再次返回 false!

console.log(tags[0] == selectedTags[0].target); // false
console.log(tags[0] == selectedTags.target[0]); // false
Run Code Online (Sandbox Code Playgroud)

我也尝试使用“价值”

console.log(tags[0] == selectedTags[0].value); // false
console.log(tags[0] == selectedTags.value[0]); // false
Run Code Online (Sandbox Code Playgroud)

我如何比较 vue 3 中同一对象的引用?

我想你明白我想要做的,计算返回非选定的项目:

let nonSelected =  computed(() =>
     props.tags.filter(t => props.selectedTags.every(s => s != t))
);
Run Code Online (Sandbox Code Playgroud)

Est*_*ask 5

问题是,它tags是常规的非反应性数组,并且selectedTags是深度反应性的,tags[0]是常规对象,并且selectedTags.value[0]是反应性对象,即Proxy实例。

为了丢弃代理,可以使用以下命令检索初始对象toRaw

toRaw(tags[0]) === toRaw(selectedTags.value[0]).id
Run Code Online (Sandbox Code Playgroud)

ref这里是不必要的,因为它没有重新分配,它可能是反应式数组。

但主要问题是tags和的反应性selectedTags无缘无故地不匹配。它们应该被定义为深度反应数组,例如(readonlyreactive),或者两者都定义为浅反应数组( ,或和 的shallowReactive组合)。reactivemarkRaw

一般来说,不会出现这样的问题,因为这种方法不适用于预期在这些地方使用的不可变对象。实现此目的的一种方法是放弃对象相等性并通过标识它们的属性来比较对象,即id

tags[0].id === selectedTags[0].id
Run Code Online (Sandbox Code Playgroud)

如有必要,可以使用可选链接。

正如所说,改变 prop 是一种不好的做法;这使得数据流变得更加复杂。相反,子级需要向父级发出selectedTags或 的列表。id