转载:探索Vue响应式API之toRefs

输入:


const {ref, reactive, toRefs} = VueReactivity;
const counter = reactive({a:1});
const counterToRefs = toRefs(counter);

toRefs函数:

function toRefs(object) {    
    if (!isProxy(object)) {      
        console.warn(        `toRefs() expects a reactive object 
            but received a plain one.`      );    
    }    
    const ret = isArray(object) ? new Array(object.length) : {};    
    for (const key in object) {      
        ret[key] = toRef(object, key);    
    }    
    return ret;  
}

这里传入进去的counter因为调用了reactive,所以是一个proxy,也就是vue中所说的响应性对象。toRefs函数首先判断传入进去的对象是不是Proxy,如果不是将会警告。因为我们传入进去的是一个Object,所以ret={}。看遍历里的toRef函数都做了什么。

function toRef(object, key) {    
    return isRef(object[key]) ? object[key] : new ObjectRefImpl(object, key);  
}

函数内判断每个key在对象内是不是一个ref,如果不是,new一个ObjectRefImpl对象。看看ObjectRefImpl。

class ObjectRefImpl {    
    constructor(_object, _key) {      
        this._object = _object;      
        this._key = _key;      
        this.__v_isRef = true;    
    }    
    get value() {      
        return this._object[this._key];    
    }    
    set value(newVal) {      
        this._object[this._key] = newVal;    
    }  
}

看的出来,做的工作很简单,实例化了一个ObjectRefImpl对象,这个对象内分别挂载了_object,_key,__v_isRef三个属性,如果触发get操作,将返回Object[key],如果触发set操作,将给Object内指定的key赋新值。

 counterToRefs的结果打印出来,可以发现,实际上toRefs函数要做的事情其实很简单,就是生成一个新的对象,对象中的每个key都对应着proxy的每个key,双方建立映射关系。对a做的任何操作实际上就是对proxy[a]做的任何操作。

看下Vue官网所说的,会思考一个问题,为什么解构的时候要用toRefs,否则将丢失反应性?

看到这里可能已经了解了,因为props是个proxy,如果不toRefs直接解构,得到的title跟原来的props没有任何关系,如果title发生了改变或被使用到,props都无法进行track(依赖收集)和trigger(触发依赖)。因此也就丢失了相应性。

而通过建立这样的映射关系,实例化了一个ObjectRefImpl对象,巧妙的解决了问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值