[javascript核心-02]彻底弄清Vue3响应式原理及手写实现

本文详细探讨Vue3的响应式原理,包括何为响应式、依赖收集、封装响应式函数、使用Proxy数据监听自动触发更新等关键步骤。通过实例解析如何手动实现响应式系统,并解决依赖重复收集问题,最终实现将对象自动用Proxy代理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 响应式原理及实现

本文github地址:JavaScript_Interview_Everything大前端知识体系与面试宝典,从前端到后端,全栈工程师,六边形战士

1.1. 何为响应式?

如果我们有一个对象:

const obj = {
   
   
    name: 'flten',
    age: 16,
}

有一些函数使用了这个对象中的数据:

function fn1(){
   
   
    console.log(obj.name)
}

function fn2(){
   
   
    console.log(obj.name)
}

如何在obj对象的属性name发生改变时,让fn1和fn2函数自动重新触发更新数据呢?

能够在数据更新时通知到所有使用到它的函数,使其重新触发,这就是响应式。

1.2. 如何区分需要响应式和非响应式

但是有些函数是使用了响应式的数据,而有些则没有,那我们如何判断呢?最简单的方式就是把所有使用到了某个数据的所有函数都保存在一个数组中,数据发生改变时直接全部遍历函数重新执行就可以了。

// 01.js
const reactiveArr = [];

const obj = {
   
   
    name: 'flten',
    age: 16,
}

function fn1(){
   
   
    console.log(obj.name)
}

reactiveArr.push(fn1)

function fn2(){
   
   
    console.log(obj.name)
}

reactiveArr.push(fn2)

reactiveArr.forEach(fn => {
   
   
    fn()
})

等一下,难道每次我们都要手动push吗?重复的操作当然是可以封装在一个函数里了

//02.js
const reactiveArr = [];

function addReactive(fn){
   
   
    reactiveArr.push(fn)
}

const obj = {
   
   
    name: 'flten',
    age: 16,
}

function fn1(){
   
   
    console.log(obj.name)
}

addReactive(fn1)

function fn2(){
   
   
    console.log(obj.name)
}

addReactive(fn2)

reactiveArr.forEach(fn=>{
   
   
    fn()
})

看起来还不错,但是这里我们只是收集了使用了name属性的函数,如果我们还要收集age属性的函数呢?这时我们就需要另外一个数组和另外一个将函数添加到数组中的方法

//03.js
const reactiveNameArr = [];
const reactiveAgeArr = [];

function addNameReactive(fn){
   
   
    reactiveNameArr.push(fn)
}

function addAgeReactive(fn){
   
   
    reactiveAgeArr.push(fn)
}

const obj = {
   
   
    name: 'flten',
    age: 16,
}

// name 属性的使用收集
function fn1(){
   
   
    console.log(obj.name)
}

addNameReactive(fn1)

function fn2(){
   
   
    console.log(obj.name)
}

addNameReactive(fn2)

reactiveNameArr.forEach(fn=>{
   
   
    fn()
})

// age属性的使用收集

function fn3(){
   
   
    console.log(obj.age)
}

addAgeReactive(fn3)

function fn4(){
   
   
    console.log(obj.age)
}

addAgeReactive(fn4)

reactiveAgeArr.forEach(fn=>{
   
   
    fn()
})

但是这样太麻烦了,每一个数据都要另外新建一个数组和添加函数吗?什么方式可以封装这些重复操作呢?它可以自动生成一个数组和对应的函数操作呢?当然是类了,我们可以通过定义一个类,为每个响应式数据都实例化一个对象,这样就把这些操作封装起来不需要每次都手动重建了。

1.3. 依赖收集

我们将上面的操作封装为一个类:

//04.js
class Depend{
   
   
    constructor(){
   
   
        this.reactiveArr = []
    }

    addDepend(fn){
   
   
        this.reactiveArr.push(fn)
    }

    notify(){
   
   
        this.reactiveArr.forEach(fn=>fn())
    }
}

const obj = {
   
   
    name: 'flten',
    age: 16,
}

const dependName = new Depend();
const dependAge = new Depend();

// name 属性的使用收集
function fn1(){
   
   
    console.log(obj.name)
}

dependName.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值