vue數據不更新的緣由(vue中數據更改了,可是視圖沒有更新)

vue數據不更新的緣由(vue中數據更改了,可是視圖沒有更新)

參考連接vue

templete:git

<div id="app">
        <h2>{{dataObj.text}}</h2>
</div>

js:github

new Vue({
            el: '#app',
            data: {
                dataObj: {}
            },
            ready: function () {
                var self = this;

                /**
                 * 異步請求模擬
                 */
                setTimeout(function () {
                    self.dataObj = {};//真正實現數據更新的是這行代碼
                    self.dataObj['text'] = 'new text';
                }, 3000);
            }
})

上面的代碼很是簡單,咱們都知道vue中在data裏面聲明的數據才具備響應式的特性,因此咱們一開始在data中聲明瞭一個dataObj空對象,而後在異步請求中執行了兩行代碼,以下:web

self.dataObj = {};
self.dataObj['text'] = 'new text';

解決辦法: 首先清空原始數據,而後添加一個text屬性並賦值。而後數據和模版都更新裏。數組

其中.text屬性不具備響應式,可是數據更新了。緣由:

vue的dom更新是異步的,即當setter操做發生後,指令並不會立馬更新,指令的更新操做會有一個延遲,當指令更新真正執行的時候,此時.text屬性已經賦值,因此指令更新模板時獲得的是新值。
具體流程以下:app

  • self.dataObj = {};發生setter操做
  • vue監測到setter操做,通知相關指令執行更新操做
  • self.dataObj[‘text’] = ‘new text’;賦值語句
  • 指令更新開始執行

因此真正的觸發更新操做是self.dataObj = {};這一句引發的,因此單看上述例子,具備響應式特性的數據只有dataObj這一層,它的子屬性是不具有的。dom

數組更新檢測

Vue 包含一組觀察數組的變異方法,因此它們也將會觸發視圖更新。這些方法以下:異步

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

注意事項

因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:svg

當你利用索引直接設置一個項時,例如:vm.items[indexOfItem] = newValue
當你修改數組的長度時,例如:vm.items.length = newLength
舉個例子:this

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是響應性的
vm.items.length = 2 // 不是響應性的

爲了解決第一類問題,如下兩種方式均可以實現和vm.items[indexOfItem] = newValue相同的效果,同時也將觸發狀態更新:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

你也可使用 vm.$set 實例方法,該方法是全局方法 Vue.set 的一個別名:

vm.$set(vm.items, indexOfItem, newValue)

爲了解決第二類問題,你可使用 splice:

vm.items.splice(newLength)

對象更改檢測注意事項

仍是因爲 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 如今是響應式的

vm.b = 2
// `vm.b` 不是響應式的

對於已經建立的實例,Vue 不能動態添加根級別的響應式屬性。可是,可使用 Vue.set(object, key, value)方法向嵌套對象添加響應式屬性。例如,對於:

var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})

你能夠添加一個新的 age 屬性到嵌套的 userProfile 對象:

Vue.set(vm.userProfile, 'age', 27)

你還可使用 vm.$set 實例方法,它只是全局 Vue.set 的別名:

vm.$set(vm.userProfile, 'age', 27)

有時你可能須要爲已有對象賦予多個新屬性,好比使用 Object.assign() 或 _.extend()。在這種狀況下,你應該用兩個對象的屬性建立一個新的對象。因此,若是你想添加新的響應式屬性,不要像這樣:

Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

你應該這樣作:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})