Vue 理解之白话 getter/setter详解
2024-06-24 11:01:59阅读量:33 字体:大 中 小
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器
以上摘自 深入响应式原理
那么,把这些属性全部转为 getter/setter 具体是怎样一个过程呢?本文不深入具体,简单大致了解其过程,旨在整体把握,理解其主要思路
假设代码如下:

data 选项可以接收一个对象或者方法,这里以对象为例(其实最后都会转为对象)
首先,这个对象的所有键值对都会被挂载在 vm._data 上(此外 vm._data 对象上还有个 __ob__ key,暂时可以忽视),这样我们便能用 vm._data.msg 访问到数据
但是通常我们是用 vm.msg 这样访问数据,如何做到的呢?其实就是做了个代理,将 data 键值对中的 vm[key] 的访问都代理到 vm._data[key] 上
通常 vm._data (下划线变量)用作内部程序,对外暴露的 API 是 vm.$data,其实这两者也是一个东西,也是做了个代理,代码大概这样:
简单理解就是访问 vm.data.msg 其实就是访问 vm._data.msg。如果直接在开发环境对 vm.data = xxx这样的赋值,而不是vm.$data.msg = xxx` 这样的赋值,后者是没问题的)
至此,我们理解了为什么能用 vm.msg、vm._data.msg 以及 vm.$data.msg 三种方式获取/改变数据,最原始的数据是 vm._data.msg,而另外两者即代理了 _data 的数据,vm.$data.msg 即为 Vue 向外提供的 API,一般情况下开发我们直接用 vm.msg 这样比较多,也方便,如果要获取整个 data,程序中需要用 this.$data,而不是 this.data
接下来说 getter/setter
将 demo 稍微添点东西:
msg2 是依赖于 msg 的,当 msg 改变的时候,msg2 的值需要自动更新,msg 的改变可以在 vm._data.msg 的 setter 中监听到,但是怎么知道 msg2 是依赖于 msg 的呢?
直观地我们可以想到,遍历所有 computed 对象的键值对,然后进行分析,理论上似乎可行,但是我寻思着这可能需要解析 AST 啊,或者正则去匹配,看看是否用到了 this.msg,也可能是 this.$data.msg 啊,还可能是 this._data.msg,而且还要遍历 data 中的所有 key,这看起来也太麻烦了吧,而且,如果程序中没有用到 msg2,那不是多此一举了?
事实上,Vue 初始化的时候会对 vm._data 的每个键值对设置 getter/setter,大概代码如下:
Vue 响应式核心就是,setter 的时候会收集依赖,getter 的时候会触发依赖更新
我们还是以上面的 computed msg2 为例,当我们第一次去取值 msg2 时(注意,必须是取值行为,可以是在 template,也可以是程序中),势必需要去取值 this.msg,这就会触发 msg 的 getter,此时我们就可以确定 msg2 依赖于 msg
msg 可以被哪些东西依赖呢?目前看来有三
template 模版中
computed
watch
我们可以打印 vm._watchers 查看,是一个 Watcher 实例数组,直接看实例的 expression 值,其实就是触发这个表达式的时候,会触发 msg 的 getter
而这个表达式就对应上述的三种情况,因为 msg 改变的时候,这些表达式需要重新求值,所以这些依赖项都要保存起来,所以源码中定于了这个 Watcher 类
A watcher parses an expression, collects dependencies, and fires callback when the expression value changes. This is used for both the $watch() api and directives.
watcher.deps 数组表示该 watcher 的依赖项,值为 Dep 实例,可以理解成和 Watcher 实例的表达式有关的 data 数据。注意,deps 数组可能是空,对于 template 而言,可以是 template 中不依赖于 data,对于 computed 而言,可以是这个 computed 数据还没被获取(比如我定义了 msg2,但是程序中没有用,这时 deps 为空,这表明我如果改变了 msg,但是不需要通知到 msg2,因为 msg2 根本没用到嘛,但是我在控制台输入 vm.msg2,从而触发了 msg 的 getter,继而进行了依赖收集,这时 deps 就不为空了,这表明我已经使用了 msg2,下次 msg 更新时需要通知到 msg2 进行改变)
而对于 watch 而言,我试了下任何情况下 deps 都不为空,这需要进一步查看源码确认
deps 数组元素是 Dep 实例,该实例有个 subs 属性,是 Watcher 实例数组,表示依赖于这个 Dep 的项目
Watcher 和 Dep 比较难理解,可以暂时这样理解,Dep 和 data 挂钩,每一个 Dep 实例就对应 data 的一个键值对,Watcher 实例则依赖于 Dep,那么有三个情况会依赖,也就是以上三种(想想是不是这样,当数据更新的时候,是不是只有这三处需要同时更新,或者同时响应)
总结下:我们会对 data 中所有键值对设置 getter/setter,getter 的时候我们会收集依赖(依赖项为上面三项,并不是任何情况下都会收集依赖,比如在钩子中打印 msg,这时候就没依赖,所以源码中这里还有复杂判断),setter 的时候我们会将收集的依赖项触发,从而更新数据,理解了这些,就能初步理解 Vue 的响应式原理。
免责声明:
本文《Vue 理解之白话 getter/setter详解》版权归原作者所有,内容不代表本站立场!
如本文内容影响到您的合法权益(含文章中内容、图片等),请及时联系本站,我们会及时删除处理。
推荐阅读

vivo手机查定位找手机
vivo手机系统有查定位找手机的功能,可以利用vivo公司的云服务功能来进行查定位找手机,操作步骤如下: vivo手机查定位找手机 1、打开手机的设置,点击首行的个人头像,进入账号中心页面中。 2、...
阅读: 742

ipad一直语音播报触屏滑不了
ipad一直语音播报触屏滑不了是因为ipad开启了旁白的功能,需要去设置内把该功能进行关闭,操作步骤如下: ipad一直语音播报触屏滑不了 1、打开ipad的设置,点击辅助功能”按钮,进入...
阅读: 813

苹果下载记录永久删除
苹果手机的下载记录是不能删除的,但是可以设置隐藏起来不显示在已购项目中,操作方法如下: 苹果下载记录永久删除 1、打开手机的App Store,点击右上角的苹果id头像,进入账户的页面。 2、点击已...
阅读: 758

vivos12分屏模式怎么开启
vivos12手机的系统自带有分屏的功能,有需要的用户可以开启手机的分屏模式,具体的操作步骤如下: vivos12分屏模式怎么开启 1、打开手机,用手指从手机屏幕的底部向上滑动,这一过程中手指不要松开...
阅读: 804

苹果睡眠起床闹钟删不掉
苹果手机系统有一个睡眠起床闹钟的功能,这个闹钟是无法删除的,但是可以进行关闭,操作步骤如下: 苹果睡眠起床闹钟删不掉 1、打开手机的时钟app,进入下方的闹钟”界面。 2、点击起床闹钟的...
阅读: 688

怎么把小红书的视频提取出来
小红书的视频可以通过保存视频的方式提取到手机上,小红书通过保存提取视频的具体步骤如下: 怎么把小红书的视频提取出来 1、打开小红书app,然后选择需要提取的视频。 2、选择需要提取的视频后,选择右上...
阅读: 1735
热门文章
1.上海公交车微信扫码支付步骤
- 1

- 上海公交车微信扫码支付步骤
- 2022-12-28
- 1
2.支付宝怎么设置花呗收款开关
- 2

- 支付宝怎么设置花呗收款开关
- 2022-12-28
- 2
3.剪映怎么局部变色
- 3

- 剪映怎么局部变色
- 2022-12-28
- 3
4.微利贷怎么申请开通
- 4

- 微利贷怎么申请开通
- 2022-12-28
- 4
5.微信怎么转发大量聊天记录
- 5

- 微信怎么转发大量聊天记录
- 2022-12-28
- 5
6.手机美图秀秀怎么移动文字
- 6

- 手机美图秀秀怎么移动文字
- 2022-12-28
- 6
7.快手怎么看不到动态消息私信
- 7

- 快手怎么看不到动态消息私信
- 2022-12-28
- 7
8.天眼查询个人信息怎么查
- 8

- 天眼查询个人信息怎么查
- 2022-12-28
- 8
9.快手登陆手机号不用了收不到验证码怎么办
- 9

- 快手登陆手机号不用了收不到验证码怎么办
- 2022-12-28
- 9
10.免费更改证件照背景色
- 10

- 免费更改证件照背景色
- 2022-12-28
- 10
最近更新

酷狗音乐中使用蝰蛇音效制作工具的具体操作方法
2024-11-11

win7电脑中出现声音图标不见了的具体解决方法
2024-11-11

车到哪app的详细软件介绍
2024-11-11

小米9se中查看序列号的具体操作方法
2024-11-11

迅雷中使用FTP探测器的详细操作方法
2024-11-11

ppt制作出小荷才露尖尖角动画场景的具体操作步骤
2024-11-11
