zoukankan      html  css  js  c++  java
  • 对vue响应式数据更新的误解

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

    对于刚接触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这一层,它的子属性是不具备的。

    对比示例:

    模板

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

  • 相关阅读:
    10. Regular Expression Matching
    Leetcode:9. Palindrome Number
    MySQL
    MyBatis Plus 自动类型转换之TypeHandler
    深拷贝和浅拷贝
    【强制】不要在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑 错误。
    【强制】日期格式化时,传入 pattern 中表示年份统一使用小写的 y。
    【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
    【强制】POJO如果继承了另一个 POJO 类,注意在前面加一下 super.toString。
    【强制】禁止使用构造方法 BigDecimal(double)的方式把 double 值转化为 BigDecimal 对象。
  • 原文地址:https://www.cnblogs.com/zhaotq/p/9392520.html
Copyright © 2011-2022 走看看