【Vue原理】代理 Data - 源码版

本文探讨Vue框架中如何通过实例直接访问data数据的原理,主要围绕2.5.17版本的Vue源码展开。文章指出,Vue通过`initData`初始化数据并保存到实例,随后进行数据代理,避免了React中访问state需要额外一层的不便。通过`Object.defineProperty`设置get和set,实现数据的响应式,确保数据统一、不影响依赖收集和更新。
摘要由CSDN通过智能技术生成

 

专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧

 

研究基于 Vue版本2.5.17

 

如果你觉得排版难看,请点击下面链接 或者 关注公众号

【Vue原理】代理 Data - 源码版

 

公众号

 

写这篇文章,我就是为了记录我对 Data 的一个疑问的探索,很简短

data 的数据是怎么可以通过实例直接访问的?

第一想法,或许是,遍历逐个复制?

但是其实并不是,这里涉及的一个词,叫 【代理】

怎么代理呢?听我慢慢说,抓住逐个疑问,跟着我慢慢探索

 

1初始化数据

 

实例使用 initData 初始化数据,如下


function initData(vm) {    

    var data = vm.$options.data;    

    var keys = Object.keys(data);    

    var i = keys.length;

   data = vm._data =

        ( typeof data === 'function' ?

            data.call(vm) : data ) || {};    



    while (i--) {        

        var key = keys[i];        

        if (只要不是_和$开头的属性) {

           proxy(vm, "_data", key);        
}    
} }

首先,拿到 data 数据,如果data 是函数,就执行拿到返回值,否则直接拿设置的对象data

第二,保存data 数据

源码中你可以看到,把 data 保存到实例上了

vm._data = 
    typeof data === 'function' ? 
        data.call(vm) : data

初始化数据,是为了拿到数据,然后放到存到实例上,作为代理总部

 

2代理开花

 

接下来,就放大招了,到了data 代理 的重点了,看上面的源码最后

会遍历data对象,如果属性名不是 _ 或者 $ 开头的话,就会被设置代理

至于为什么避开那两个开头的属性?

Vue官网也说明了

image.png

剩下的其他属性,会被设置代理,现在我们来看设置代理的那句话

proxy(vm,"_data",key)

proxy 是什么?不要急,等我放上源码

function proxy(target, sourceKey, key) {    

    Object.defineProperty(target, key, {

       get() {            

            return this[sourceKey][key]

       },

       set(val) {            

            this[sourceKey][key] = val;

       }    }); }

明白吗?通过 Object.defineProperty 设置 get 和 set 函数,来达到代理,移花接木的过程

可能这么看不太直观,我以一个属性为例写清楚点

image.png

于是就会设置成这样

image.png

下面是给 _data 属性设置响应式的简化代码

image.png

 

这样的作用,有四个

1、可以直接通过 vm 访问到name

简化写法,你看看 React 这个比,访问 state,需要 this.state.xxx 写多一层 很麻烦啊,Vue 做了一层代理就很好,但是呢,成本会大一些

2、保证数据统一

如果是开篇想的那样,逐个赋值,数据改变的时候,就要同时维护两份啊,简直是地狱啊。但是 methods 的处理是直接复制到实例上的

3、不影响依赖收集

当访问 【vm.name】,触发代理 【vm.name 设置的get】,就会访问 【vm._data.name】 ,从而触发总部 【vm._data.name 设置的get】,这个get 用来依赖收集。最后完全不会影响

4、不影响依赖更新

赋值 【vm.name】,触发代理 【vm.name 设置的 set】,就会直接赋值给总部 【vm._data.name】 ,从而触发 【vm._data.name 设置的set 】,这个set,用来依赖更新。最后完全不会影响

 

 

最后

鉴于本人能力有限,难免会有疏漏的地方,请大家多多包涵,旨在交流,如果有任何描述不当的地方,欢迎后台联系本人,领取红包

如果你能转发一下,就更好啦,技术人交流 只用文章

长按关注>>>

image.png

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值