对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属性是不具有响应式特性的。

相关文章
相关标签/搜索