• Vue检测数据的原理


    Vue能够对用户的数据进行响应式,也就是你在data中写了什么,你在模板中用到data的部分就会渲染成什么,那么Vue是怎么知道用户修改了data中的数据变化并对模板重新进行解析的呢?

    在Vue将数据存储为自身的_data之前,Vue会将数据进行处理,主要用到的仍然是数据代理,通过修改一个对象中的属性触发getter和setter进行设置。

    如果不清楚数据代理的流程,可以参考这篇文章:https://blog.csdn.net/XunLin233/article/details/133714989

    一、Vue监测对象的修改 

    我们使用数据代理的方式对p对象中的name属性进行数据代理: 

    1. const p = {
    2. name:"张三",
    3. age:18
    4. }
    5. Object.defineProperty(p, "name", {
    6. get() {
    7. return p.name;
    8. },
    9. set(value) {
    10. p.name=value;
    11. }
    12. })

    但是我们按照上面的写法进行数据的读取和修改的时候就会报错:

    03.html:18 Uncaught RangeError: Maximum call stack size exceeded 

    为什么会产生这个原因呢?

    当我们读取name属性时,就会调用get函数,get函数中又读取name属性,又调用get函数...如此无限套娃,就报错了。

     

    如何解决上面问题呢?

    既然不能通过对象本身去修改属性值,那我们就借助其他的对象来对属性值进行修改,然后返回这个将所有属性修改后的对象,其核心思想就是为每一个对象属性设置getter和setter。

    我们可以使用构造函数的this为一个对象中添加属性:

    1. const p = {
    2. name:"张三",
    3. age:18
    4. }
    5. function Observer(obj) {
    6. // 获取对象所有的属性名
    7. const keys = Object.keys(obj);
    8. // 对对象的每个属性进行遍历
    9. keys.forEach((k)=>{
    10. // 这里的this是Observe对象,所有修改后的属性都添加在了Observe对象身上
    11. console.log(this); // Observer {}
    12. Object.defineProperty(this, k, {
    13. // 添加getter 和 setter
    14. get() {
    15. return obj[k];
    16. },
    17. set(value) {
    18. console.log("数据被修改了");
    19. obj[k] = value;
    20. }
    21. })
    22. })
    23. }
    24. const newp = new Observer(p); // 创建Observe对象
    25. console.log(newp);

     

    Vue的底层逻辑就是通过上述方法监视数据的修改,但是Vue源码能够监视更深层次的数据修改,如: 对象中存储对象的形式。

    二、Vue.$set()

    当我们想给一个对象添加新的属性时,我们该怎么做呢?

    例如下面的代码,在data中有一个person对象,里面有name和age属性,但是我们想添加再添加一个age属性

    当我们在vm._data上的person对象添加sex 时并没有用:

     

    如果我们打开vm._data的话,会发现name和age都有get和set,只有sex没有,说明Vue并没有几监视添加的sex对象。 

     Vue提供了 Vue.$set() 方法来进行对象的添加属性:

    Vue.$set( 目标对象, 属性名称, 属性值 )

    我们使用该方法添加的属性拥有数据代理 

     

    在代码中可以直接使用this.$set进行调用 

     

    注意:Vue.$set() 不能在data上直接添加属性!

    报错:vue.js:5108  [Vue warn]: Avoid adding reactive properties to a Vue instance or its root $data at runtime - declare it upfront in the data option. 

    三、Vue检测数组的修改

    我们使用v-for遍历一个数组:

    现在我们想将数组中下标为0的元素改为“篮球”,但是我们修改过后页面并没有改变 

    如果我们输出vm._data 会发现数组中的每一个元素都没有getter和setter,因此Vue不能检测数据的变化。

     

    那我们要怎样去改变数组呢?

    Vue规定使用如下方法修改数组能够被监测到修改:

    push()

    pop()

    shift()

    unshift()

    splice()

    sort()

    reverse() 

    要注意的是,上面这些方法是Vue重新包装过的方法,不再是原来Array对象上的方法

    Vue的包装过程不仅调用原始Array中的方法,还对页面模板重新进行了解析。 

  • 相关阅读:
    2.6每日一题(不定积分)
    【deepstream部署Yolov6】
    [Centos]Docker卸载/安装&常用命令
    NET 6 实现滑动验证码(一)、创建工程
    【vue3】状态过渡-GSAP插件实现
    学习MySQL-第六章
    全面解析优化企业Microsoft 365网络的加速方案
    day4-聚类文章CONVEX BICLUSTERING
    15-js运动函数和轮播图
    C语言函数概述——拜佛代码
  • 原文地址:https://blog.csdn.net/XunLin233/article/details/133865600