这里是我读文章注意到的问题:
- 注意到data方法中的属性
- 就是vue只有写到data中的才会去绑定监听他的变化, 例如对象obj中如果在data外面新添加的属性obj.test就不会被监听可以看下面两个文章
- 日常请求数据时直接赋值是响应式的没问题
- 一般是当我们例如分段请求时, 例如在数组中新添加的数据就不会监听到, 就需要watch监听, 或者使用set方法去实现响应式
- 可以看到下面的watch例子, 就是等待dom更新一次后再去刷新
对于刚接触vue的同学会经常遇到数据更新了但是模板没有更新的问题,下面将结合vue的响应式特性以及异步更新机制分析常见的错误:
异步更新带来的数据响应式误解
异步数据的处理基本是一定会遇到的,处理不好就会遇到数据不更新的问题,但有一种情况是在未正确处理的情况下也能正常更新,这就会造成一种误解,详情如下所示:
- 模板
<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属性并赋值。到这里为止一切都如我们所想的,数据和模板都更新了。
那么问题来了,dataObj.text具有响应式的特性吗?
--
模板更新了,应该具有响应式特性,如果这么想那么你就已经走入了误区,一开始我们并没有在data中声明.text属性,所以该属性是不具有响应式的特性的。
但模板切切实实已经更新了,这又是怎么回事呢?
那是因为vue的dom更新是异步的,即当setter操作发生后,指令并不会立马更新,指令的更新操作会有一个延迟,当指令更新真正执行的时候,此时.text属性已经赋值,所以指令更新模板时得到的是新值。
具体流程如下所示:
self.dataObj = {};发生setter操作- vue监测到setter操作,通知相关指令执行更新操作
self.dataObj['text'] = 'new text';赋值语句- 指令更新开始执行
所以真正的触发更新操作是self.dataObj = {};这一句引起的,所以单看上述例子,具有响应式特性的数据只有dataObj这一层,它的子属性是不具备的。
注:其实vue文档中已经有说明,对于新增以及删除的属性,vue是无法监测到的。
var a = {};
a.b = 0; //新增b属性
a = {
c: 0
}; //更改a属性的值
上述两种赋值方式对vue造成的影响是不同的。
对比示例:
模板
<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属性是不具备响应式特性的。