對vue響應式數據更新的誤解

對於剛接觸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

那麼問題來了,dataObj.text具備響應式的特性嗎?

--

模板更新了,應該具備響應式特性,若是這麼想那麼你就已經走入了誤區,一開始咱們並無在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>

js

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

                /**
                 * 異步請求模擬
                 */
                setTimeout(function () {
                    self.dataObj['text'] = 'new text';
                }, 3000);
            }
        })

上述例子的模板是不會更新的。

Vue.$set

經過$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屬性是不具有響應式特性的。

相關文章
相關標籤/搜索