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

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

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

Vue2的响应式是基于Object.defineProperty实现的
Vue3的响应式是基于ES6的Proxy来实现的
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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值