2017-01-23 29 views
2

私はVue Frameworkを新しく導入しました。属性が追加または削除されるたびに、または後の段階でコンポーネント外で更新されるたびに、親から子への変更を伝播しようとしています。以下のスニペットでは、親ノードからプロパティとして渡されるノードのname属性に基づいて挨拶メッセージを表示するコンポーネントを記述しようとしています。vue JSが親からコンポーネントへの変更を伝播しない

ノードが初期化時に(名前がスニペットである)属性 "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"> 
 
\t <h1>{{message.name}}</h1> 
 
</script>

編集1:クレイグの答え@属性名に属性のそれぞれのセットを呼び出すことによって基づいて変更を伝播するために私を助けます。しかし、データが複雑で、挨拶がノードの多くの属性に基づいている場合はどうでしょうか。ここでは単純な使用例を示していますが、実際には、ウィジェットはサーバーから動的に送信される多くの属性に基づいており、各ウィジェットの属性はウィジェットのタイプによって異なります。 "ようこそ、{{message.name}}。{{message.location}}の温度は{{message.temp}}です。ノードの属性が異なるため、javascriptコード内のツリー全体をトラバースせずに完全なツリーを更新し、各属性の呼び出しセットを更新する方法はありますか?これを処理できるVUEフレームワークには何かがありますか?あなたがする必要があるので、:あなたはsetメソッドを使用しない限り

答えて

5

Vueは(https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveatsを参照してください):プロパティの追加または削除を検出することはできません

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

はここJSFiddleです:https://jsfiddle.net/f7ae2364/

EDIT

あなたの場合、私はあなたがpropを見捨てることを断念し、 event busあなたのデータを通過することを避けたい場合。

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

と聞く:あなたが更新されたデータをバス上にあなたの$emitイベントを新しいデータを受信したときに次に

var bus = new Vue({}); 

:だから、最初にあなたがでリッスンするコンポーネントのためのグローバル・バスを設定しました

created(){ 
    bus.$on('data-updated', (message) => { 
    this.message = message; 
    this.$forceUpdate(); 
    }) 
} 
:(作成されたフックの内側に配置することができます)あなたのコンポーネントの内部にそのイベントのために、再レンダリングコンポーネント(私はここ ES6を使用しています)へのメッセージと力 vueを更新

ここにJSFiddleがあります:https://jsfiddle.net/9trhcjp4/

+0

更新のおかげで、データが複雑で、挨拶がノードの多くの属性に基づいていた場合はどうなりますか?ここでは単純な使用例を示していますが、実際には、ウィジェットはサーバーから動的に送信される多くの属性に基づいており、各ウィジェットの属性はウィジェットのタイプによって異なります。 "ようこそ、{{message.name}}。{{message.location}}の温度は{{message.temp}}です。ノードの属性が異なるため、ツリー全体をトラバースせずにツリー全体を更新し、各属性の呼び出しセットを更新する方法はありますか? – Ajay

+0

さらに、data.name = 'Changed world'を追加するとコードが機能しませんVueの前に .set(データ、 '名前'、 '変更されたワールド1')。これは、オブジェクトがスコープの外で既に更新されていて、セット操作でさえ同じキーに設定している間は助けにならないということです。どのようにこの制限を克服するためのアドバイス?ありがとう@クレイグ。 – Ajay

+0

ソリューションは不具合なく動作します。 – Ajay

関連する問題