例如下面情況:
templete:
<div id="app"> <h2>{{dataObj.text}}</h2> </div>
js:
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空對象,然后在異步請求中執行了兩行代碼,如下:
self.dataObj = {};
self.dataObj['text'] = 'new text';
解決辦法: 首先清空原始數據,然后添加一個text屬性並賦值。然后數據和模版都更新里。
其中.text屬性不具有響應式,但是數據更新了。原因:
vue的dom更新是異步的,即當setter操作發生后,指令並不會立馬更新,指令的更新操作會有一個延遲,當指令更新真正執行的時候,此時.text屬性已經賦值,所以指令更新模板時得到的是新值。
具體流程如下:
self.dataObj = {};發生setter操作
vue監測到setter操作,通知相關指令執行更新操作
self.dataObj[‘text’] = ‘new text’;賦值語句
指令更新開始執行
所以真正的觸發更新操作是self.dataObj = {};這一句引起的,所以單看上述例子,具有響應式特性的數據只有dataObj這一層,它的子屬性是不具備的。
數組更新檢測
Vue 包含一組觀察數組的變異方法,所以它們也將會觸發視圖更新。這些方法如下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
注意事項
由於 JavaScript 的限制,Vue 不能檢測以下變動的數組:
當你利用索引直接設置一個項時,例如:vm.items[indexOfItem] = newValue
當你修改數組的長度時,例如:vm.items.length = newLength
舉個例子:
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' })
參考文獻:https://blog.csdn.net/weixin_41767649/article/details/82797373