vue JS没有将更改从父组件传播到组件



我是Vue Framework的新手。每当添加或删除属性,或者在稍后阶段在组件外部更新属性时,我都会尝试将更改从父级传播到子级。在下面的片段中,我试图编写一个组件,该组件显示基于节点的name属性的问候消息,该属性作为属性从父节点传递。

如果节点在初始化时包含属性"name"(在下面注释的片段中),则一切都可以正常工作。但是,如果添加了name属性,则会在稍后的执行阶段执行(为了演示目的,我添加了一个设置超时并应用)。组件抛出错误,并且更改不会反映出来。我不确定如何在组件中传播动态属性的更改,这些更改是基于组件外部的其他事件生成的。

基本上,我想更新组件,该组件根据传递给它的属性以动态方式根据服务器响应显示不同类型的小部件。每当属性更新时,我都希望组件更新自己。为什么双向绑定在Vuejs中不能正常工作?

Vue.component('greeting', {
template: '#treeContainer',
props: {'message':Object},
watch:{
'message': {
handler: function(val) {
console.log('###### changed');
},
deep: true
}
}
});
var data = {
note: 'My Tree',
// name:"Hello World",
children: [
{ name: 'hello' },
{ name: 'wat' }
]
}
function delayedUpdate() {
data.name='Changed World';
console.log(JSON.stringify(data));
}
var vm = new Vue({
el: '#app',
data:{
msg:data
},
method:{ }
});
setTimeout(function(){ delayedUpdate() ;}, 1000)
<script src="https://vuejs.org/js/vue.js"></script>
<div id="app">
<greeting :message="msg"></greeting>
</div>
<script  type="text/x-template"  id="treeContainer">
	<h1>{{message.name}}</h1>
</script>

编辑1:@Craig的回答帮助我根据属性名称并通过对每个属性调用set来传播更改。但是,如果数据很复杂,并且问候语基于节点的许多属性,该怎么办。在这个例子中,我经历了一个简单的用例,但在现实世界中,小部件基于从服务器动态发送的许多属性,每个小部件的属性根据小部件的类型而不同。比如"欢迎使用,{{message.name}}。{{message.location}处的温度为{{message.temp}"等等。由于节点的属性不同,有没有任何方法可以更新完整的树,而无需遍历javascript代码中的整棵树并对每个属性调用集。VUE框架中有什么可以解决这一问题的吗?

Vue无法检测属性添加或删除,除非使用set方法(请参阅:https://v2.vuejs.org/v2/guide/reactivity.html#Change-检测注意事项),所以你需要做:

Vue.set(data, 'name', 'changed world')

以下是JSFiddle:https://jsfiddle.net/f7ae2364/

编辑

在您的情况下,如果您想避免遍历数据,我认为您将不得不放弃观看prop,而选择事件总线。因此,首先你为你的组件设置了一个全局总线来监听:

var bus = new Vue({});

然后,当您收到新数据时,您将事件$emit发送到带有更新数据的总线上:

bus.$emit('data-updated', data);

并在组件中侦听该事件(可以放置在创建的挂钩中),更新消息并强制vue重新呈现组件(我在这里使用ES6):

created(){
bus.$on('data-updated', (message) => {
this.message = message;
this.$forceUpdate();
})
}

以下是JSFiddle:https://jsfiddle.net/9trhcjp4/