2017-05-30 57 views
0

我知道像這樣的問題有很多,但這個問題有點不同。我把AA看reactivity in depth,認爲我對這個問題一個公平的理解,有一件事我不能,雖然理解是這樣的:爲什麼觀看的對象沒有在vue中更新

TL;博士

爲什麼當currentValue = Object.assign=({}, currentValue, initValue)初始化做了觀察的屬性寄存器的變化但沒有直接轉讓currentValue = initValue;

我有一個註冊的對象,scoreRules我VUE組件的模型

mounted鉤,

  1. 我模特的scoreRules使用

    this.$data.scoreRules = initScoreRules;

    (重新初始化initScoreRules作爲道具傳入,但是我聲明爲爲了這個問題的目的,本地的 變量)。

  2. 手錶scoreRules當對象發生變化時,更改和日誌「分數已更改」。

此片段展示了此方案

new Vue({ 
 
    el: '#app', 
 
    data() { 
 
    return { 
 
     scoreRules: { 
 
     type: "number", 
 
     minimum: null, 
 
     maximum: null 
 
     } 
 
    } 
 
    }, 
 
    mounted() { 
 
    let initScoreRules = {type: "number"}; 
 
    this.$data.scoreRules = initScoreRules; 
 
    this.$watch('scoreRules',()=>{console.log("score has been changed")}, {deep: true}); 
 
    } 
 
});
<html> 
 

 
<head> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script> 
 
</head> 
 

 
<body> 
 
    <div id="app"> 
 
    <span>Minimum score</span> 
 
    <input type="number" name="minimumScore" v-model.number="scoreRules.minimum" /> 
 
</body> 
 

 
</html>

現在,當我輸入的東西到輸入,手錶不抓住這個變化,並沒有什麼記錄到控制檯。

如果我現在使用 this.$data.scoreRules = Object.assign({}, this.$data.scoreRules, initScoreRules);

new Vue({ 
 
    el: '#app2', 
 
    data() { 
 
    return { 
 
     scoreRules: { 
 
     minimum: null 
 
     } 
 
    } 
 
    }, 
 
    mounted() { 
 
    let initScoreRules = {}; 
 
    this.$data.scoreRules = Object.assign({}, this.$data.scoreRules, initScoreRules); 
 
    this.$watch('scoreRules',() => { 
 
     console.log("score has been changed") 
 
    }, { 
 
     deep: true 
 
    }); 
 
    } 
 
});
<html> 
 

 
<head> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.js"></script> 
 
</head> 
 

 
<body> 
 
    <div id="app2"> 
 
    <span>Minimum score</span> 
 
    <input type="number" v-model.number="scoreRules.minimum" /> 
 
    </div> 
 
</body> 
 

 
</html>

完成變更登記,並輸出記錄到控制檯重新初始化scoreRules。爲什麼?我懷疑它與JS本身的內部有關,但我不確定如何。

+2

對象是引用類型。這就是爲什麼你需要用'Object.assign'克隆一個對象,而不是用'='指向現有的對象。當您創建一個新對象時,Vue有可能爲對象及其屬性設置反應環境。 – wostex

+0

我明白了。使用'='直接賦值將指向一個無反應的對象,並因此更改爲未註冊的對象。現在看起來很明顯。謝謝。 –

回答

1

最初的對象包含屬性minimummaximum。然後,在mounted,你這樣做:

let initScoreRules = {type: "number"}; 
this.$data.scoreRules = initScoreRules; 

這意味着現在scoreRules對象不具有這些屬性。

的Vue只能觀察變化到要麼屬性:

  • 預先定義在data()(你沒有,但然後在mounted未那樣)
  • 組具有Vue.set()/this.$set()
  • 本在分配給反應性屬性的對象上。

最後一點也是爲什麼第二個例子作品的解釋:在這裏,基本上你這樣做(再走出來Object.assign冗長,因爲它是分散注意力):

this.$data.scoreRules = { minimum: null }; 

此屬性將是反應。

更多在這裏閱讀:

https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats

+1

謝謝@Linus。總結完美。 –

相關問題