我观察到当来自data()
的普通属性和从它派生的计算属性通过事件传递时,前者保持其反应性而后者失去它。
我为它设置了以下测试用例(also as a JSFiddle如果您愿意的话):
const EventBus = new Vue();
Vue.component('comp', {
data() {
return {
arrData: ['a', 'b']
};
},
computed: {
arrComputed() {
return this.arrData.map((e) => e.toUpperCase());
}
},
template: `
<div>
<div>Original array: {{ arrData }}</div>
<div>Computed array: {{ arrComputed }}</div>
<button @click="remove('a')">Remove a</button>
<button @click="remove('b')">Remove b</button>
<button @click="pass">Pass through event</button>
<button @click="reset">Start over soft</button>
<button @click="resetHard">Start over hard</button>
</div>`,
methods: {
remove(name) {
name = name.toLowerCase();
if(this.arrData.indexOf(name) != -1) {
this.$delete(this.arrData, this.arrData.indexOf(name));
}
},
pass() {
EventBus.$emit('pass', this.arrData, this.arrComputed);
},
reset() {
this.$set(this.arrData, 0, 'a');
this.$set(this.arrData, 1, 'b');
},
resetHard() {
this.arrData = ['a','b'];
}
}
});
Vue.component('othercomp', {
data() {
return {
items1: [],
items2: []
}
},
mounted() {
EventBus.$on('pass', this.receive);
},
template: `
<div>
<div>Original array: {{items1}}</div>
<div>Computed array: {{items2}}</div>
</div>`,
methods: {
receive(items1, items2) {
this.items1 = items1;
this.items2 = items2;
}
}
});
var app = new Vue({
el: '#app',
components:['comp', 'othercomp']
})
&#13;
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
<comp></comp>
<othercomp></othercomp>
</div>
&#13;
计算结果与普通属性有何不同,以便发生这种行为差异?
我从previous question了解到,像这样传递反应性物体是不好的做法,我应该使用吸气剂功能,但是我仍然想知道为什么会出现这种差异。
答案 0 :(得分:1)
我不希望这会起作用。通过返回map()
的结果,您将反应数组的副本传递给另一个组件。此副本不会对原始数组的更改做出反应 - 它是一个完全不同的数组。即使计算属性将在arrData
更改时更新,它也不会自动向第二个组件发送另一个事件,告诉它更新它的数据数组。我认为你需要在两个组件上都有一个计算属性 - 你可以用drin方式使用mixin或filter(在这种情况下可能更合适)。
你可以在计算函数中触发事件。但这对我来说似乎非常讨厌:
arrComputed() {
let newArray = this.arrData.map((e) => e.toUpperCase());
EventBus.$emit('pass', this.arrData, newArray);
return newArray
}
答案 1 :(得分:1)
我观察到当来自data()和a的普通属性时 从中派生的计算属性通过事件传递, 前者保持其反应性而后者失去它。
对象变量(Array是对象)包含对象的引用(或句柄)。将一个对象变量分配给另一个时,将复制该句柄,并且这两个变量都是一个对象的句柄。一个上的对象操作将被另一个“看到”。
所以
之后foo = [1];
bar = foo;
foo.push(2);
foo
和bar
,,因为它们引用相同的对象,将是[1, 2]
。传递值的工作方式相同,但使用简单的赋值更容易说明。
应该很清楚
foo = [1];
bar = foo;
foo = [1, 2];
为foo
分配一个新句柄,因此它不再引用bar
所做的同一个数组。
在您的示例中,arrComputed
每次arrData
更改时都会创建一个新的Array对象。因此,当您传递arrComputed
时,您将传递它上次运行时创建的句柄。当arrData
更改时,arrComputed
会创建一个新的Array对象,但旧句柄的收件人不会得到该对象,并且永远不会更新与其句柄关联的数组。