2017-08-07 78 views
1

我的根目錄中有兩個對象 - objnewObj。我在deep: true上觀察我的obj對象上的更改,並在更改時相應地更新newObj。Vue - 組件道具不能正確觀察對象的變化

在我的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

可以嘗試更新照片直接'this.newObj'而不是內部'this.newObj'鍵。您可以在最後使用'this.newObj = JSON.parse(JSON.stringify(this.newObject))'作弊。 'deep:true'申請obj不適用於newObj,所以如果參考未更新,UI不會更新 – Epitouille

+0

但是,如何才能夠附加到現有密鑰值?難道它只是覆蓋現有的價值,並只保留這個項目?我會很感激任何指導 – senty

+0

你可以附加到現有的鍵值,但你需要告訴vuejs你的對象已經改變,它應該重新渲染。 Vuejs默認情況下,只監視newObj的引用,這意味着如果你改變這個對象:this.newObj = otherObject,它會起作用。我不確定這是你的問題,這就是爲什麼你應該測試我的建議。或者使用Object.assign或其他東西來更改引用,並查看UI是否更新。 – Epitouille

回答

1

你的數據newObj具有由VUE定義的getter和setter。當調用者被調用時,UI被重新渲染。當您更改參考newObj時,而不是在您更改其值時,觸發器會被觸發。我的意思是:

this.newObj = {} // triggered 

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

您可以在屬性this.newObj上添加深層觀察者。或者改變它的參考:

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

其中創建對象的副本newObject

這裏是小提琴更新。

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個方法(this。$ set和Object.assign) – Epitouille