我有这个代码。它纯粹是出于实验目的:
test.html
<div id="example-1">
{{ stuff.dosobject.notlist }}
<button v-on:click="dostuff">DO STUFF</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="test.js"></script>
test.js
var oneobject={
dosobject:{
notlist:"foo"
}
}
var stuff = Object.create(oneobject)
var example1 = new Vue({
el: '#example-1',
data: {
stuff:stuff
},
methods:
{
dostuff:function(event)
{
if(stuff.dosobject.notlist=="foo")
stuff.dosobject.notlist="bar"
else
stuff.dosobject.notlist="foo"
}
}
})
对象stuff
是用oneobject
作为原型创建的。
我希望属性stuff.dosobject.notlist
是反应性的,即单击按钮时将重新渲染模板的{{ stuff.dosobject.notlist }}
部分。
似乎并非如此。
我做错什么了吗?还是正常的VueJS行为?
考虑了一下之后,似乎并没有使所有原型属性都具有响应性,这似乎并不奇怪,因为原型链可能会很长,并会导致性能问题。
答案 0 :(得分:0)
通常,解决这些类型的反应性警告的方法是使用Vue.set
:
向反应对象添加属性,确保新属性为 还具有反应性,因此触发视图更新。这必须用于添加新 属性,因为Vue无法检测到正常属性 添加内容(例如
this.myObject.newProperty = 'hi'
)。
但是,Vue.set
包含以下检查:
if (key in target && !(key in Object.prototype)) { target[key] = val return val }
我已阅读并重新阅读Reactivity in Depth,其中指出:
当您将普通 JavaScript对象传递给Vue实例...(重点是我)
因此,很明显,您不应该传递复杂的对象并且期望反应性起作用。但是,原型继承是“普通”对象的一部分,当您使用类,第三方库或大型,复杂的代码库时,有时不可避免地要处理作为道具或数据传递的“非普通”对象。
通过使用Vue.set
“使反应性”现有对象很好,但是由于进行了in
检查,它不会将原型值复制到对象并设置反应性吸气剂/设定剂对。
您可以尝试以下两种解决方案:
克隆对象而不是从对象继承,以确保stuff
具有dosobject
作为own property。
在stuff
上设置任何属性时触发$forceUpdate
,或为stuff
创建proxy以在set
陷阱中自动执行
在遇到的极端情况下,我们设置了一个函数以确保我们设置的更改被Vue的反应系统吸收:
function setPropertyReactive(obj, key, value) {
if (obj.hasOwnProperty(key)) {
obj[key] = value;
return;
}
delete Object.getPrototypeOf(obj)[key];
Vue.set(obj, key, value);
}