手写vue3响应系统

目录

1.目标:

2.原理

3.实现代码

4.小结:


1.目标:

假设我现在有一个对象obj

let obj = {text:"hello 小明"}

还有一个函数effect

function effect (){
//document.body.innerHTMl看作是页面上的值
  document.body.innerHTMl = obj.text
}

我们希望修改值obj.text = "hello vue3"时,effect函数页执行,使得页面数据发生变化 

想要的效果是修改obj.text的值,页面也跟着变化,这就是响应式。

再明确一下目标:修改对象的值,使页面自动更新我们修改的最新值(数据)


2.原理

vue2使用的是obj.defineproperty函数实现,而vue3使用的proxy代理对象实现,这里使用proxy。

完成上述的目的有两个重要的信息:


第一个时当执行effect的时候会触发obj.text的读取操作

第二个是当修改obj.text的时候会触发obj.text的设置操作

当然,重头戏就是代理对象proxy来实现了


3.实现代码

const bucket = new Set() //类数组结构,用来存储effect函数

const data = {text:"hello xiaoming"} //原始数据

const obj = new Proxy(data,{

    //拦截读取操作
    get(target,key){
    //将effect添加到bucket
    bucket.add(effect)
    //返回属性值
    return targrt[key]
    
         },
    //拦截设置操作
    set(target,key,newval){

    //设置属性值
    target[key] = newval
    //把effect从bucket中取出来并执行
    bucket.forEach(fn => fn())
    //返回true代表设置成功
    return true
    }

})

接下来执行以下看效果

function effect(){
    document.body.innerHTML = obj.text
}

effect()//执行

//过1秒后执行修改,看看页面是否变化

setTimeout(()=>{
    obj.text = "看看修改成功了没有"
},1000)

ps:肯定有人疑问为啥bucket是干嘛的,其实就是为了实现页面变化,细品一下。

这个bucket的作用就是修改dom元素使页面及时变化

要理解proxy”代理“这两个字,举个简单的例子,本来有一个苹果,但是想要的是苹果汁,那么在苹果变成苹果汁的过程可以看作被代理了,这么理解的话,proxy就很容易理解了。


4.小结:

到目前为止,响应式数据完成了,但是不够完善,但这就是响应式原理的最简单实现代码。后续我会写一个完善版的响应式文章。

在上面,我们创建了一个存储副作用的桶bucket,他是set类型。接着定义原始数据类型data,obj是原始数据的代理对象,我们分别设置了get 和 set拦截函数,用于拦截和读取操作。当读取属性时将副作用effect函数放到桶里,即bucket.add(effect),然后返回属性值。当设置属性值时先更新原始数据,然后将副作用函数从桶里取出来并且执行,这样我们就实现了响应式数据。

猜你喜欢

转载自blog.csdn.net/wanghaoyingand/article/details/125494046