基于Proxy、Map、WeakMap实现响应式数据

基于Proxy、Map、WeakMap实现响应式数据,跟着视频学习梳理思路模仿了一遍。底部为全部代码。深入JavaScript高级语法-coderwhy大神新课-学习视频教程-腾讯课堂该课程的核心目的是深入学习JavaScript的核心语法,特别是JavaScript比较复杂的、难以理解的一些概念和特性,进行深入细致的讲解。本课程能帮助你在前端技术学习、面试、工作、项目应用上,承上启下,融会贯通,不管你是前端在职工作者还是初学者,此课程都非常值得学习。https://ke.qq.com/course/3619571

思路一:

根据对象set、get实现访问修改执行对应方法,并使用Proxy代理,封装到resFunc函数中可在创建对象时直接绑定事件。

Proxy MDN

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

// 代理对象
function resFunc(obj) {
    return new Proxy(obj, {
        // get
        get(target, key, receiver) {
            return Reflect.get(target, key, receiver); //返回对应的值
        },
        // set
        set(target, key, newValue, receiver) {
            Reflect.set(target, key, newValue, receiver); //修改对应的值
        }
    })
}

 

思路二 :

保存对象的响应式方法,可以WeakMap来进行储存,(优势:可以使用对象作为key存储对应的事件)同一属性存在多个事件时,使用Map存储(优势:避免重复存储方法)。

WeakMap MDN

WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的。

描述:

WeakMap 的 key 只能是 Object 类型。 原始数据类型 是不能作为 key 的(比如 Symbol)。 

 Map MDN

Map 对象保存键值对,并且能够记住键的原始插入顺序。任何值(对象或者原始值) 都可以作为一个键或一个值。

// 处理保存的方法
const targetMap = new WeakMap() //所有的响应式方法,以对象作为key存储

//创建方法,每次调用set时保存方法
function getDepend(target, key) {
    // 根据对象保存
    let map = targetMap.get(target);  //根据target=对象,获取当前对象中储存的所有属性绑定的方法
    if (!map) {
        map = new Map()
        targetMap.set(target, map)
    }
    // 根据属性保存
    let depend = map.get(key); //根据属性获取方法
    if (!depend) {
        depend = new Depend()
        map.set(key, depend)
    }

    return depend //返回进行下一步调用
}

 

思路三:

封装保存方法的函数

// 封装一个响应式的函数
function watchFn(fn) {
    activeReactiveFn = fn
    fn()
    activeReactiveFn = null
}
// 测试
function test1() {
    console.log(ResObj1.name);
}
watchFn(test1)

 

思路四:

对重复事件封装

// 创建类保存对象响应式方法
class Depend {
    constructor() {
        this.ResObjFunc = new Set()
    }

    addFunc() {
        activeReactiveFn ? this.ResObjFunc.add(activeReactiveFn) : ''
    }

    notify() {
        this.ResObjFunc.forEach(func => {
            func()
        })
    }
}

代码完善

// 创建变量保存方法
let activeReactiveFn = null

// 创建类保存对象响应式方法
class Depend {
    constructor() {
        this.ResObjFunc = new Set()
    }

    addFunc() {
        activeReactiveFn ? this.ResObjFunc.add(activeReactiveFn) : ''
    }

    notify() {
        this.ResObjFunc.forEach(func => {
            func()
        })
    }
}


// 处理保存的方法
const targetMap = new WeakMap()

function getDepend(target, key) {
    // 根据对象保存
    let map = targetMap.get(target);
    if (!map) {
        map = new Map()
        targetMap.set(target, map)
    }
    // 根据属性保存
    let depend = map.get(key);
    if (!depend) {
        depend = new Depend()
        map.set(key, depend)
    }

    return depend
}


// 代理对象
function resFunc(obj) {
    return new Proxy(obj, {
        // get
        get(target, key, receiver) {
            // 执行对应方法
            const depend = getDepend(target, key);
            depend.addFunc()

            return Reflect.get(target, key, receiver); //返回对应的值
        },
        // set
        set(target, key, newValue, receiver) {
            Reflect.set(target, key, newValue, receiver); //修改对应的值

            // 执行对应方法
            const depend = getDepend(target, key);
            depend.notify()
        }
    })
}

// 封装一个响应式的函数
function watchFn(fn) {
    activeReactiveFn = fn
    fn()
    activeReactiveFn = null
}


// 创建响应式对象
let ResObj1 = resFunc({
    name: 'pxq',
    age: 18
})


// 测试
function test1() {
    console.log(ResObj1.name);
}

function test2() {
    console.log(ResObj1.age);
}

watchFn(test1)
watchFn(test2)
ResObj1.name = 'wxf'
ResObj1.age = 20

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值