Vue3的响应式原理?

提示:记录工作中遇到的需求及解决办法


前言

其实Vue3已经出来很久了,可能大部分公司都用上了,但是,Vue3究竟比Vue2好在哪里?其实很多人都不知道。今天我就先给大家讲一讲 Vue3的响应式原理吧,顺便说一说 Vue3的响应式到底比Vue2的响应式好在哪


好在哪?

好的,咱们先来讲讲为什么 Vue3的响应式 优于 Vue2响应式。可能平时问大家:请问你知道Vue的响应式是怎么实现的吗?大家都能粗略回答出来

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

是的,虽然上面的回答抽象了点,但是确实是回答出了Vue的两个版本的响应式的核心原理,并且Vue的两个版本响应式的好坏,也确实就是体现在 Object.definePropertyProxy 的差异上。

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

通过上面的例子,我想大家都对 Object.defineProperty 有了一个了解,那问题来了?它到底有什么弊端呢?使得尤大大在Vue3中抛弃了它,咱们接着看:

// 接着上面代码

data.hobby = '打篮球'
console.log(data.hobby) // 打篮球
data.hobby = '打游戏'
console.log(data.hobby) // 打游戏

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

Vue3

从上面,咱们知道了 Object.defineProperty 的弊端,咱们接着讲Vue3中响应式原理的核心 Proxy 是怎么弥补这一缺陷的,老样子,咱们还是举例子(先粗略讲,具体参数下面会细讲):

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}`)
      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

可以看到,其实效果与上面的Object.defineProperty没什么差别,那为什么尤大大要抛弃它,选择Proxy呢?注意了,最最最关键的来了,那就是对象新增属性,来看看效果吧:

proxyData.hobby = '打篮球'
console.log(proxyData.hobby)
// 访问了hobby属性
// 打篮球
proxyData.hobby = '打游戏'
// 将hobby由->打篮球->设置成->打游戏
console.log(proxyData.hobby)
// 访问了hobby属性
// 打游戏

所以现在大家知道Vue3的响应式比Vue2好在哪了吧?
在这里插入图片描述

Vue3响应式原理

说完 Proxy 的好处,咱们正式来讲讲Vue3的响应式原理的核心部分吧。

前言

先看看下面这段代码

let name = '林三心', age = 22, money = 20
let myself = `${
     name}今年${
     age}岁,存款${
     money}`

console.log(myself) // 林三心今年22岁,存款20元

money = 300

// 预期:林三心今年22岁,存款300元
console.log(myself) // 实际:林三心今年22岁,存款20元

大家想一下,我想要让 myself 跟着 money 变,怎么办才行?嘿嘿,其实,只要让 myself = '${name}今年${age}岁,存款${money}元' 再执行一次就行,如下

let name = '林三心', age = 22, money = 20
let myself = `${
     name}今年${
     age}岁,存款${
     money}`

console.log(myself) // 林三心今年22岁,存款20元

money = 300

myself = `${
     name}今年${
     age}岁,存款${
     money}` // 再执行一次

// 预期:林三心今年22岁,存款300元
console.log(myself) // 实际:林三心今年22岁,存款300元

effect

上面说了,每一次 money 改变就得再执行一次 myself = '${name}今年${age}岁,存款${money}元' ,才能使 myself 更新,其实这么写不优雅,咱们可以封装一个 effect函数

let name = '林三心', age = 22, money = 20
let myself = ''
const effect = () => myself = `${
     name}今年${
     age}岁,存款${
     money}`

effect() // 先执行一次
console.log(myself) // 林三心今年22岁,存款20元
money = 300

effect() // 再执行一次

console.log(myself) // 林三心今年22岁,存款300元

其实这样也是有坏处的,不信你可以看看下面这种情况

let name = '林三心', age = 22, money = 20
let myself = '', ohtherMyself = ''
const effect1 = () => myself = `${
     name}今年${
     age}岁,存款${
     money}`
const effect2 = () => ohtherMyself = `${
     age}岁的${
     name}居然有${
     money}`

effect1() // 先执行一次
effect2() // 先执行一次
console.log(myself) // 林三心今年22岁,存款20元
console.log(ohtherMyself) // 22岁的林三心居然有20元
money = 300

effect1() // 再执行一次
effect2(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿超学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值