【Vue原理】代理 Data - 源码版
栏目: JavaScript · 发布时间: 5年前
内容简介:写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧 研究基于 Vue版本如果你觉得排版难看,请点击
写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧 研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面 关注公众号 也可以吧
写这篇文章,我就是为了记录我对 Data 的一个疑问的探索,很简短
data 的数据是怎么可以通过实例直接访问的?
第一想法,或许是,遍历逐个复制?
但是其实并不是,这里涉及的一个词,叫 【代理】
怎么代理呢?听我慢慢说,抓住逐个疑问,跟着我慢慢探索
初始化数据
实例使用 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官网也说明了
剩下的其他属性,会被设置代理,现在我们来看设置代理的那句话
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 函数,来达到代理,移花接木的过程
可能这么看不太直观,我以一个属性为例写清楚点
于是就会设置成这样
下面是给 _data 属性设置响应式的简化代码
这样的作用,有四个
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,用来依赖更新。最后完全不会影响
以上所述就是小编给大家介绍的《【Vue原理】代理 Data - 源码版》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
正则表达式在线测试
正则表达式在线测试
RGB CMYK 转换工具
RGB CMYK 互转工具