• vue响应式详解


    1. 响应式的定义

    我们都知道,vue是基于javascript的,那我们使用一段javascript代码来描述响应式

    let a = 1,b = 1,c;
    c = a + b;
    console.log(c) // 输出 2
    // 改变 a的值
    a = 3;
    // 重新给c赋值 即把  c = a + b; 再执行一遍c的值才能变为 4
    // c = a + b;
    // 再次输出c
    console.log(c) // 输出 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    看到没有,c的值并没有随着a的值或者b的值的改变而改变,这就不是响应式的。
    故本人粗略定义一下 当一个变量依赖于其他变量时,其他任意一个变量的改变,这个变量也会自动做出相应的改变即变量会随着依赖项变量的改变而自动改变。

    vue2和vue3的响应式实现有什么区别?

    Vue2的响应式是基于Object.defineProperty实现的
    Vue3的响应式是基于ES6的Proxy来实现的
    
    • 1
    • 2
    vue2

    Vue2的响应式是基于Object.defineProperty的,那我就拿Object.defineProperty来举个例子

    // 响应式函数
    function reactive(obj, key, value) {
        Object.defineProperty(data, key, {
          get() {
            console.log(`访问了${key}属性`)
            return value
          },
          set(val) {
            console.log(`${key}由->${value}->设置成->${val}`)
            if (value !== val) {
              value = val
            }
          }
        })
      }
      
      const data = {
        name: '林三心',
        age: 22
      }
      Object.keys(data).forEach(key => reactive(data, key, data[key]))
      console.log(data.name)
      // 访问了name属性
      // 林三心
      data.name = 'sunshine_lin' // 将name由->林三心->设置成->sunshine_lin
      console.log(data.name)
      // 访问了name属性
      // sunshine_lin
    
      data.grade = 80;
      console.log(data.grade) // 80
    
      data.grade = 90;
      console.log(data.grade) // 90
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    data新增了grade属性,进行访问和设值,但是都不会触发get和set,所以弊端就是:Object.defineProperty只对初始对象里的属性有监听作用,而对新增的属性无效。这也是为什么Vue2中对象新增属性的修改需要使用Vue.$set来设值的原因。

    vue3
    const data = {
      name: '林三心',
      age: 22
    }
    
    function reactive(target) {
      const handler = {
        get(target, key, receiver) {
          console.log(`访问了${key}属性`)
          return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
          console.log(`${key}由->${target[key]}->设置成->${value}`)
          // 注意定义 Proxy 代理对象的 set 的时候,要返回 return true 不然报错  
          // 解决 https://blog.csdn.net/LawssssCat/article/details/104561640
          return Reflect.set(target, key, value, receiver)
        }
      }
    
      return new Proxy(target, handler)
    }
    
    const proxyData = reactive(data)
    
    console.log(proxyData.name)
    // 访问了name属性
    // 林三心
    proxyData.name = 'sunshine_lin'
    // 将name由->林三心->设置成->sunshine_lin
    console.log(proxyData.name)
    // 访问了name属性
    // sunshine_lin
    
    proxyData.grade = 80; // 将grade由->undefined->设置成->80
    console.log(proxyData.grade) // 访问了grade属性 80
    
    proxyData.grade = 90; // 将grade由->80->设置成->90
    console.log(proxyData.grade) // 访问了grade属性 90
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述
    参考大神博客
    参考vue3官网
    至于vue3具体的实现代码过于八股文,有兴趣的朋友可以看看。

  • 相关阅读:
    Redis中有大量未设置过期时间的缓存应该如何处理?
    鸿蒙原生应用/元服务开发-AGC分发如何编译打包应用
    CMake Tutorial 巡礼(3)_添加库的使用需求
    Java中的泛型(Generics)
    virtualbox 下载安装
    自定义类加载器
    通配符指什么呢?
    软考网络工程师 第四章 第四节 最小帧长计算
    【Unity基础】1.项目搭建与视图编辑
    经纬恒润智能感知后视镜亮相北京车展
  • 原文地址:https://blog.csdn.net/weixin_46591962/article/details/132684185