Vue - 组件道具没有正确观察对象变化
Posted
技术标签:
【中文标题】Vue - 组件道具没有正确观察对象变化【英文标题】:Vue - component props not watching object changes properly 【发布时间】:2018-01-15 00:51:47 【问题描述】:我的根目录中有两个对象 - obj
和 newObj
。我用deep: true
观察我的obj
对象的变化,并在变化时相应地更新newObj。
在我的 vue 调试器中,newObj
似乎已按预期更新,但是该组件不执行 for 循环计数。或者如果我尝试 newObj
,它只会记录第一次更新。
我尝试重新创建问题on this Fiddle。
我的html:
<div id="app">
<button @click="appendTo">Append</button>
<my-comp v-bind:new-obj="newObj"></my-comp>
</div>
和Vue:
new Vue(
el: '#app',
data:
obj: ,
newObj:
,
methods:
appendTo()
if (typeof this.obj[1] === 'undefined')
this.$set(this.obj, 1, )
var randLetter = String.fromCharCode(Math.floor(Math.random() * (122 - 97)) + 97);
this.$set(this.obj[1], randLetter, [ [] ])
,
watch:
obj:
handler(obj)
var oldKeys = Object.keys(obj)
var newKeys = Object.keys(this.newObj);
var removedIndex = newKeys.filter(x => oldKeys.indexOf(x) < 0 );
for (var i = 0, len = removedIndex.length; i < len; i++)
delete this.newObj[removedIndex[i]]
oldKeys.map((key) =>
if (this.newObj.hasOwnProperty(key))
var newInnerKeys = Object.keys(this.newObj[key]);
var oldInnerKeys = Object.keys(obj[key]);
var additions = oldInnerKeys.filter(x => newInnerKeys.indexOf(x) < 0);
for (var i = 0, len = additions.length; i < len; i++)
// here
this.$set(this.newObj[key], additions[i], [ [] ]);
var deletions = newInnerKeys.filter(x => oldInnerKeys.indexOf(x) < 0);
for (var i = 0, len = deletions.length; i < len; i++)
delete this.newObj[key][deletions[i]]
else
this.newObj[key] =
for (var innerKey in obj[key])
this.$set(this.newObj, key,
[innerKey]: [ [] ]
);
console.log(obj);
console.log(this.newObj)
);
,
deep: true
)
Vue.component('my-comp',
props: ['newObj'],
template: `
<div>
<div v-for="item in newObj">
test
</div>
</div>
`
)
【问题讨论】:
您可以尝试更新直接this.newObj
而不是this.newObj
中的密钥。最后你可以用this.newObj = JSON.parse(JSON.stringify(this.newObject))
作弊。 deep: true
申请 obj 而不是 newObj 所以如果引用没有更新,UI 也不会更新
但是,我如何才能附加到现有的键值?它不会只是覆盖现有值并仅保留此项目吗?我将不胜感激任何指导
您可以附加到现有的键值,但您需要告诉 vuejs 您的对象已更改并且应该重新渲染。 Vuejs 默认只看 newObj 的引用,这意味着如果你像这样改变这个对象:this.newObj = otherObject,它会起作用。我不确定这是你的问题,这就是为什么你应该测试我的建议。或者使用 Object.assign 或其他东西来更改引用并查看 UI 是否更新。
问题是,我不想完全复制obj里面的东西,我想在newObj里面放不同的数据,但是根据obj里面的变化。这就是为什么我不能使用this.newObj = otherObj
。还是我误解了您的解决方案?如果您能添加答案或将其放在小提琴中,我将不胜感激..
fiddle 不灵了,扔到控制台:Uncaught ReferenceError: Vue is not defined at window.onload
【参考方案1】:
你的数据newObj
有一个由 vue 定义的 getter 和 setter。调用 setter 时,会重新渲染 UI。当您更改 newObj
的 reference 时触发 setter,而不是在您更改其值时触发。我的意思是:
this.newObj = // triggered
this.newObj['key'] = 'value' // not triggered
您可以在属性this.newObj
上添加深度观察者。或者用技巧改变它的引用:
this.newObj = Object.assign(, this.newObjec);
创建对象newObject
的副本。
这里是更新的小提琴。
https://jsfiddle.net/749nc5d2/
【讨论】:
我做了var scalfold = this.newObj[key]; delete this.newObj[key]
然后this.$set(this.newObj, key, scalfold)
- 它奏效了.. 你认为这是一个错误的方法吗? (只是出于好奇而询问。您的方法似乎非常清晰和正确。刚刚测试它,它就像魅力一样)
vuejs.org/v2/guide/reactivity.html 这是一个非常有趣的链接。默认情况下,只有对象的引用是响应式的。反应式意味着,更新 UI(以及当值改变时的其他东西)。 this.$set
将键添加到将是反应性的对象。因此,当您第一次创建 this.newObj
时,您可以使用 this.$set 创建它,您的对象将是完全反应式的。下面的链接显示了 2 个方法(this.$set 和 Object.assign)以上是关于Vue - 组件道具没有正确观察对象变化的主要内容,如果未能解决你的问题,请参考以下文章