对vue响应式数据更新的误解

本文摘自https://segmentfault.com/a/1190000007787941?_ea=1459649,为个人笔记

对于刚接触vue的同学会经常遇到数据更新了但是模板没有更新的问题,下面将结合vue的响应式特性以及异步更新机制分析常见的错误:

异步更新带来的数据响应式误解

异步数据的处理基本是一定会遇到的,处理不好就会遇到数据不更新的问题,但有一种情况是在未正确处理的情况下也能正常更新,这就会造成一种误解,详情如下所示:

  • 模板

1
2
3
<div id="app">
        <h2>{{dataObj.text}}</h2>
</div>
  • js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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空对象,然后在异步请求中执行了两行代码,如下:

1
2
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这一层,它的子属性是不具备的。

对比示例:

模板

1
2
3
<div id="app">
        <h2>{{dataObj&&dataObj.text}}</h2>
</div>

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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属性是不具备响应式特性的。

posted @   tianqi.zhao  阅读(300)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示