温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

vue响应式Object代理对象的修改和删除属性是什么

发布时间:2022-08-04 11:29:00 来源:亿速云 阅读:167 作者:iii 栏目:开发技术

这篇“vue响应式Object代理对象的修改和删除属性是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue响应式Object代理对象的修改和删除属性是什么”文章吧。

set

set就是修改代理的属性,按照我们之前写的reactive,它大概是这样的

const ITERATE_KEY=symbol()
const p = new Proxy(obj,{
 set(target,key,newVal,receiver){
        const res = Reflect.set(target,key,newVal,receiver)
        trigger(target,key)
        return res
  }
}

细心的朋友应该发现了,我专门把ITERATE_KEY也加进来了,但是在set中并没有使用,难道是多余的?

这里其实有一个小坑,就是如果曾经对对象使用过for ... in,这里会出现2种情况:

  • 如果我们新增了一个属性,那么我们是不是应该重新运行一次for ... in的副作用函数。

  • 如果我们只是修改某个属性而不是新增,那么我们就不应该重新运行for ... in的副作用函数. 所以我们需要判断一下它是新增还是修改

//定义常量,在ts中可以使用枚举
const TriggerType = {
    SET:'SET',
    ADD:'ADD'
}
const p = new Proxy(obj,{
 set(target,key,newVal,receiver){
         //判断新增还是修改
         const type = Object.prototype.hasOwnProperty.call(target,key) 
         ? TriggerType.SET
         : TriggerType.ADD
        const res = Reflect.set(target,key,newVal,receiver)
        trigger(target,key,type)
        return res
  }
}

同时,对应trigger函数中,我们也需要根据type读取ITERATE_KEY对应的副作用函数.

const trigger = (target,key,type)=>{
    const depsMap = targetMap.get(target)
    if(!depsMap){
        return 
    }
    const effects = depsMap.get(key)
    // 再次去重
    const needToRun = new Set()
    if(effects){
        effects.forEach(e=> e!==activeEffect
            ? needToRun.add(e)
            : ''
        )
    }
    if(type === TriggerType.ADD){
        const otherEffects = depsMap.get(ITERATE_KEY)
        if(otherEffects){
            otherEffects.forEach(e=> e!==activeEffect
                ? needToRun.add(e)
                : ''
            )
        }
    }
    if(needToRun.length){
        needToRun.forEach(fn=> fn?.options?.scheduler ? fn.options.scheduler(fn) : fun())
    }
}

这样,我们只在新增的时候才会调用for ... in的副作用函数。

delete

删除的时候,之前貌似没写过。这里需要注意2个点。

  • 保证属性删除之后才运行副作用,这里从逻辑上讲我们最好先验证这个属性是否存在,避免报错。

  • 删除时也要运行for ... in的副作用函数

因此我们这样定义,给TriggerType新增一个类型DEL

const TriggerType = {
    SET:'SET',
    ADD:'ADD',
    DEL:'DELETE'
}

然后,我们开始拦截删除属性的操作,查一下之前的Proxy内部方法的表,我们可以得知,删除属性对应着deleteProperty方法。

const p = new Proxy(obj,{
 deleteProperty(target,key){
         //判断属性存在,你总不能删除一个不存在的属性吧
        const hadKey = Object.prototype.hasOwnProperty.call(target,key)  
        const res = Reflect.deleteProperty(target,key)
        if(res && hadKey){
            trigger(target,key,TriggerType.DEL)
        }
        return res
  }
}

对应trigger函数中,我们小修改一下,其他逻辑不变

// 删除这句
- if(type === TriggerType.ADD){
// 改为
+ if([TriggerType.ADD,TriggerType.DEL].includes(type)){

这样就可以实现响应式对象的删除属性。

其实原文中并没有使用Array.includes,但我觉得其实我们应该使用最新的语法,现在浏览器环境对这些新语法支持度已经很好了(如果你要兼容IE当我没说)。

以上就是关于“vue响应式Object代理对象的修改和删除属性是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI