vue JS 不将更改从父级传播到组件

vue JS not propagating changes from parent to component

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

如果节点在初始化时包含属性 "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 来传播更改。但是如果数据很复杂并且问候语是基于节点的许多属性呢?在示例中,我经历了一个简单的用例,但在现实世界中,小部件基于从服务器动态发送的许多属性,并且每个小部件属性因小部件类型而异。像 "Welcome, {{message.name}} . Temperature at {{ message.location }} is {{ message.temp}} . " 等等。由于节点的属性不同,有没有什么方法可以更新完整的树,而无需在我们的 javascript 代码中遍历整个树,并在每个属性上调用集。VUE 框架中有什么可以解决这个问题的吗? ?

Vue 无法检测到 属性 添加或删除,除非你使用 set method (see: https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats),所以你需要做:

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

这是 JSFiddle:https://jsfiddle.net/f7ae2364/

编辑

在你的情况下,我认为如果你想避免遍历你的数据,你将不得不放弃观看 prop 而是去观看 event bus。所以,首先你要为你的组件设置一个全局总线来监听:

var bus = new Vue({});

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

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

并在您的组件内监听该事件(可以放置在创建的钩子内),更新消息并强制 vue 到 re-render 组件(我正在使用 ES6这里):

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

这是 JSFiddle:https://jsfiddle.net/9trhcjp4/