读Vue源码二 (响应式对象)
vue在init的时候会执行observer方法,如果value是对象就直接返回,如果对象上没有定义过_ob_这个属性,就 new Observer实例
export function observe (value: any, asRootData: ?boolean): Observer | void {
if (!isObject(value) || value instanceof VNode) {
return
}
let ob: Observer | void
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if (
shouldObserve &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
ob = new Observer(value)
}
if (asRootData && ob) {
ob.vmCount++
}
return ob
}
Observer 方法,实例化一个dep是在做依赖收集时用的,调用def方法给对象添加_ob_这个属性,如果是数组就遍历给每个数组中的值都添加_ob_,否则调用walk方法
export class Observer {
value: any;
dep: Dep;
vmCount: number; // number of vms that has this object as root $data
constructor (value: any) {
this.value = value
this.dep = new Dep()
this.vmCount = 0
def(value, '__ob__', this)
if (Array.isArray(value)) {
const augment = hasProto
? protoAugment
: copyAugment
augment(value, arrayMethods, arrayKeys)
this.observeArray(value)
} else {
this.walk(value)
}
}
walk方法其实就是把对象的每个key调用defineReactive方法
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
defineReactive方法就是将其变为响应式对象,首先调用observer方法如果对象的key还是对象,会再次执行一遍上面的逻辑,如果不是对象会在oberver方法中直接返回,然后就是给对象添加setter和
getter将其变为响应式
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
const dep = new Dep() const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
} // cater for pre-defined getter/setters
const getter = property && property.get
if (!getter && arguments.length === 2) {
val = obj[key]
}
const setter = property && property.set
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend()
if (childOb) {
childOb.dep.depend()
if (Array.isArray(value)) {
dependArray(value)
}
}
}
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (process.env.NODE_ENV !== 'production' && customSetter) {
customSetter()
}
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
childOb = !shallow && observe(newVal)
dep.notify()
}
})
}
读Vue源码二 (响应式对象)的更多相关文章
- vue源码之响应式数据
分析vue是如何实现数据响应的. 前记 现在回顾一下看数据响应的原因. 之前看了vuex和vue-i18n的源码, 他们都有自己内部的vm, 也就是vue实例. 使用的都是vue的响应式数据特性及$w ...
- 读 vue 源码一 (为什么this.message能够访问data里面的message)
12月离职后,打算在年后再找工作了,最近陆陆续续的看了黄轶老师的vue源码解析,趁着还有几天过年时间记录一下. 目标:vue如何实现通过this.key,就能直接访问data,props,method ...
- 读Vue源码 (依赖收集与派发更新)
vue的依赖收集是定义在defineReactive方法中,通过Object.defineProperty来设置getter,红字部分主要做依赖收集,先判断了Dep.target如果有的情况会执行红字 ...
- 通用后台管理系统源码,响应式布局,Java管理系统源码,零门槛安装部署
本项目是一个通用响应式管理后台,导入开发环境安装就能直接运行,界面也非诚漂亮,在PC端和移动端也是自适应的.非常适合企业或者个人搭建各种商城后台,博客后台,网站管理后台等. 源码启动后的截图 需要这套 ...
- Vue2源码解读 - 响应式原理及简单实现
直接进入主题了,想必大家都知道实现vue响应式核心方法就是 Object.defineProperty,那就从它开始说 Object.defineProperty 缺点: 深度监听,需要递归到底,一次 ...
- JGUI源码:响应式布局简单实现(13)
首先自我检讨下,一直没有认真研究过响应式布局,有个大致概念响应式就是屏幕缩小了就自动换行或者隐藏显示,就先按自己的理解来闭门造车思考实现过程吧. 1.首先把显示区域分成12等分,bootstrap是这 ...
- java 企业门户网站 源码 自适应响应式 freemarker 静态引擎 html5 SSM
官网 http://www.fhadmin.org/ 系统介绍: 1.网站后台采用主流的 SSM 框架 jsp JSTL,网站后台采用freemaker静态化模版引擎生成html 2.因为是生成的ht ...
- 跟我一起读postgresql源码(二)——Parser(查询分析模块)
上篇博客简要的介绍了下psql命令行客户端的前台代码.这一次,我们来看看后台的代码吧. 十分不好意思的是,上篇博客我们只说明了前台登陆的代码,没有介绍前台登陆过程中,后台是如何工作的.即:后台接到前台 ...
- Vue源码------------- 数据响应系统的基本思路
在 Vue 中,我们可以使用 $watch 观测一个字段,当字段的值发生变化的时候执行指定的观察者,如下: var vm = new Vue({ data: { num:1 } }) vm.$watc ...
随机推荐
- iOS 如何查看APP的jetsamEvent日志
1.如何在iPhone上查看 设置-通用-分析-分析数据- JetsamEvent+日志 打头的系统日志. 2.如何在Mac 上查看此类分析日志 1.手机链接MAC 2.打开iTunes,点开手机图标 ...
- DOM---节点关系
DOM可以说是把文档当成一种树状结构,这种结构被称为节点树,JavaScript脚本可以通过节点树访问所有节点,可是执行修改或者是删除它们的内容,同时也可以创建新的节点. 节点之间的关系是有上下级别的 ...
- linux cp 拷贝文件或目录
cp 拷贝文件或目录 默认不能拷贝目录 常用来备份: [root@MongoDB ~]# cp a.txt /tmp/ [root@MongoDB ~]# cp /root/a.txt /tmp/ c ...
- linux服务器情况
查看Linux 进程命令 ps -aux 或者ps -ef linux 进程很多 如果需要查找某一个进程可以使用 管道和grep命令 Linux下常用命令 grep 匹配字符 ps 查询Li ...
- 【心得】-NO.114.面试.1 -【To HR And Interviewer】
Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total Hours:1 Degree Of Diffculty:5 Degree Of ...
- 《linux就该这么学》第十一节课: 第九章,网卡绑定与sshd服务
8.4.服务的访问控制列表 TCPwrappers是RHEL7中默认启用的流量监控程序,能够对服务做出允许或拒绝. TCPwrappers服务由两个文件控制: /etc/hosts.allow ...
- wangEditor编辑器 Vue基本配置项
wangEditor编辑器 Vue基本配置项 1.Vue安装方法 npm i wangeditor -S <template> <div id='wangeditor'> &l ...
- IDEA 破解_补丁永久_2018.3
主要是Eclipse我已经玩坏了三次了,切换jdk8到jdk10,再切换到jdk8,大量文件乱码,怎么改都没用,有的时候Eclipse久了不用,项目放在里面发霉了,坏掉了,MMP,换到I ...
- OpenStack-Neutron-Fwaas-代码【一】
Kilo的代码中对Fwaas做了优化,可以将规则应用到单个路由上 但是juno里面还是应用到租户的所有路由上的,因此对juno的代码做了修改 1. 介绍 在FWaaS中,一个租户可以创建多个防火墙,而 ...
- vue命令行错误处理
全局安装vue/cli时:npm install -g @vue/cli (1)Error: EACCES: permission denied, access '/usr/local/lib/nod ...