2017-08-07 4 views
1

ルートに2つのオブジェクトがあります。objnewObjです。私は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> 
    ` 
}) 
+0

あなたはdireclty 'this.newObj'とthis.newObj''内側のないキーを更新しようとすることができます。最後に、 'this.newObj = JSON.parse(JSON.stringify(this.newObject))'で不正行為をすることができます。 'deep:true'はnewObjのobjには適用されませんので、参照が更新されていなければUIは更新されません – Epitouille

+0

しかし、既存のキー値にどのように追加することができますか?既存の値を上書きして、このアイテムだけを保持するのではないでしょうか?私はどんな指導にも感謝します – senty

+0

既存のキー値に追加することはできますが、オブジェクトが変更されたことをvuejsに伝える必要があります。 VuejsはデフォルトでnewObjの参照のみを監視します。このオブジェクトを変更すると、this.newObj = otherObjectのようになります。私はこれがあなたの問題であるかどうかわからないので、これが私の提案をテストすべき理由です。あるいは、Object.assignや他のものを使って参照を変更し、UIが更新されているかどうか確認してください。 – Epitouille

答えて

1

あなたのデータnewObjはVUEによって定義されたゲッターとセッターを持っています。 setterが呼び出されると、UIが再レンダリングされます。設定値は、の参照newObjに変更されたときにトリガーされます。値を変更した場合は変更されません。私は意味:

this.newObj = {} // triggered 

this.newObj['key'] = 'value' // not triggered 

あなたは財産this.newObjに深いウォッチャーを追加することができます。オブジェクトnewObjectのコピーを作成

this.newObj = Object.assign({}, this.newObjec); 

:またはトリックとその参照を変更します。

ここでフィドルが更新されました。

https://jsfiddle.net/749nc5d2/

+0

私は 'var scalfold = this.newObj [key];を実行しました。 this.newObj [key] 'を削除してから' this。$ set(this.newObj、key、scalfold) ' - それが働いた..それは間違ったアプローチだと思いますか? (ちょうど好奇心から尋ねるだけです。あなたの方法はとても明確で正しい方法です。ちょうどそれを試してみて、それは魅力的です) – senty

+0

https://vuejs.org/v2/guide/reactivity.htmlここは非常に興味深いリンクです。デフォルトでは、オブジェクトの参照のみがリアクティブです。リアクティブは、UI(および値が変更されたときに他のもの)を更新することを意味します。 'this。$ set'は反応するオブジェクトにキーを追加します。ですから、初めてthis.newObjを作成すると、$ setを使って作成することができ、あなたのオブジェクトは完全に反応します。以下のリンクは2つのメソッドを示しています(これは$ setとObject.assignです) – Epitouille

関連する問題