對於剛接觸vue的同窗會常常遇到數據更新了可是模板沒有更新的問題,下面將結合vue的響應式特性以及異步更新機制分析常見的錯誤:html
異步數據的處理基本是必定會遇到的,處理很差就會遇到數據不更新的問題,但有一種狀況是在未正確處理的狀況下也能正常更新,這就會形成一種誤解,詳情以下所示:vue
模板app
<div id="app"> <h2>{{dataObj.text}}</h2> </div>
jsdom
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屬性並賦值。到這裏爲止一切都如咱們所想的,數據和模板都更新了。this
模板更新了,應該具備響應式特性,若是這麼想那麼你就已經走入了誤區,一開始咱們並無在data中聲明.text
屬性,因此該屬性是不具備響應式的特性的。code
但模板切切實實已經更新了,這又是怎麼回事呢?htm
那是由於vue的dom更新是異步的,即當setter操做發生後,指令並不會立馬更新,指令的更新操做會有一個延遲,當指令更新真正執行的時候,此時.text
屬性已經賦值,因此指令更新模板時獲得的是新值。對象
具體流程以下所示:io
self.dataObj = {};
發生setter操做
vue監測到setter操做,通知相關指令執行更新操做
self.dataObj['text'] = 'new text';
賦值語句
指令更新開始執行
因此真正的觸發更新操做是self.dataObj = {};
這一句引發的,因此單看上述例子,具備響應式特性的數據只有dataObj這一層,它的子屬性是不具有的。
對比示例:
<div id="app"> <h2>{{dataObj&&dataObj.text}}</h2> </div>
new Vue({ el: '#app', data: { dataObj: {} }, ready: function () { var self = this; /** * 異步請求模擬 */ setTimeout(function () { self.dataObj['text'] = 'new text'; }, 3000); } })
上述例子的模板是不會更新的。
經過$set方法能夠將添加一個具有響應式特性的屬性,而且其子屬性也具有響應式特性,可是必須是新屬性才能夠,若是是自己已有的屬性該方法是不起做用的。
new Vue({ el: '#app', data: { dataObj: {} }, ready: function () { var self = this; /** * 異步請求模擬 */ setTimeout(function () { var data = { name: 'xiaofu', age: 18 }; var data01 = { name: 'yangxiaofu', age: 19 }; self.dataObj['person'] = {}; self.$set('dataObj.info', data); self.$set('dataObj.person', data01); }, 3000); } })
如上所示,.person
屬性是不具有響應式特性的。