浅析Vue响应式原理(三)
Vue响应式原理之defineReactive
defineReactive
不论如何,最终响应式数据都要通过defineReactive来实现,实际要借助ES5新增的Object.defineProperty。
defineReactive接受五个参数。obj是要添加响应式数据的对象;key是属性名,val是属性名对应的取值;customSetter是用户自定义的setter;会在响应式数据的setter中执行,只有开发环境可用;通过shallow指定是否浅比较,默认深比较。
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
}
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()
}
})
}
在函数内,首先实例化一个Dep实例dep,dep会在稍后添加为响应式数据自定义的get/set中发挥作用。接着获取属性描述符,如果属性不可配置,则无法调用Object.defineProperty来修改setter/getter,所以返回。
如果原来已设置过setter/getter,缓存起来。当未自定义getter且arguments长度为2(即只传入了obj和key)时,可以直接用方括号求值,使用闭包变量val缓存初始值。
如果不是浅复制,执行observe(val),为val添加__ob__属性并返回__ob__指向的Observer实例。(只有数组和对象才可能是响应式,才能返回Observer实例)。
使用Object.defineProperty为obj[key]设置getter和setter。
在get内,如果原来已设置过getter,则用缓存的getter求值,否则使用闭包变量val作为返回值;同时添加依赖。此处为两个Dep实例添加依赖。dep是闭包变量,在getter/setter中会使用到。另一个Dep实例是childOb.dep,只用调用set/delete更新响应式数据时,才会触发;如果value是数组,还会遍历元素,为存在__ob__属性的元素收集依赖。
在set内,先获取更新前的值(逻辑和get内第一步一样)。判断更新前后的值是否相等,相等时直接返回;不等时,如果有缓存的setter,调用缓存的setter更新,否则直接赋值。值得注意的是,NaN === NaN是不成立的,反而NaN !== NaN是成立的,后面的判断语句newVal !== newVal && value !== value就是为了避免newVal/val都是NaN。在更新后的值newVal上执行observe,更新闭包变量childOb,并调用notify。
参考链接
原文地址:https://segmentfault.com/a/1190000017216175
浅析Vue响应式原理(三)的更多相关文章
- 浅析vue响应式原理
图很清晰 当我们把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 g ...
- 详解Vue响应式原理
摘要: 搞懂Vue响应式原理! 作者:浪里行舟 原文:深入浅出Vue响应式原理 Fundebug经授权转载,版权归原作者所有. 前言 Vue 最独特的特性之一,是其非侵入性的响应式系统.数据模型仅仅是 ...
- 深入Vue响应式原理
深入Vue.js响应式原理 一.创建一个Vue应用 new Vue({ data() { return { name: 'yjh', }; }, router, store, render: h =& ...
- vue响应式原理解析
# Vue响应式原理解析 首先定义了四个核心的js文件 - 1. observer.js 观察者函数,用来设置data的get和set函数,并且把watcher存放在dep中 - 2. watcher ...
- 深度解析 Vue 响应式原理
深度解析 Vue 响应式原理 该文章内容节选自团队的开源项目 InterviewMap.项目目前内容包含了 JS.网络.浏览器相关.性能优化.安全.框架.Git.数据结构.算法等内容,无论是基础还是进 ...
- Vue源码--解读vue响应式原理
原文链接:https://geniuspeng.github.io/2018/01/05/vue-reactivity/ Vue的官方说明里有深入响应式原理这一节.在此官方也提到过: 当你把一个普通的 ...
- vue响应式原理,去掉优化,只看核心
Vue响应式原理 作为写业务的码农,几乎不必知道原理.但是当你去找工作的时候,可是需要造原子弹的,什么都得知道一些才行.所以找工作之前可以先复习下,只要是关于vue的,必定会问响应式原理. 核心: / ...
- 深入解析vue响应式原理
摘要:本文主要通过结合vue官方文档及源码,对vue响应式原理进行深入分析. 1.定义 作为vue最独特的特性,响应式可以说是vue的灵魂了,表面上看就是数据发生变化后,对应的界面会重新渲染,那么响应 ...
- 浅谈vue响应式原理及发布订阅模式和观察者模式
一.Vue响应式原理 首先要了解几个概念: 数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率. 双向绑定:数据改变,视图 ...
随机推荐
- springboot 2+ druid
springboot 1+ druid druid 配置 import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid ...
- Redis List类型学习
- 多线程同步锁和死锁以及synchronized与static synchronized 的区别
线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程.一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序.简而言之:一个程序运行后至少有一个进程,一个进程 ...
- Leetcode513. Find Bottom Left Tree Value找树左下角的值
给定一个二叉树,在树的最后一行找到最左边的值. 示例 1: 输入: 2 / \ 1 3 输出: 1 示例 2: 输入: 1 / \ 2 3 / / \ 4 5 6 / 7 输出: 7 注意: 您可以假 ...
- JavaScript RegExp 对象的三种方法
JavaScript RegExp 对象有 3 个方法:test().exec() 和 compile().(1) test() 方法用来检测一个字符串是否匹配某个正则表达式,如果匹配成功,返回 tr ...
- 让pandoc输出pdf时支持中文
主机环境为:Ubuntu 12.04 LTS.对于RH系列,yum安装包的名称可能会有不同,不过yum联想能力比较强,应该不是问题. 安装pandoc,安装tex-live sudo apt-get ...
- PAT甲级——A1061 Dating
Sherlock Holmes received a note with some strange strings: Let's date! 3485djDkxh4hhGE 2984akDfkkkkg ...
- PAT甲级——A1014 Waiting in Line
Suppose a bank has N windows open for service. There is a yellow line in front of the windows which ...
- SVN添加自动忽略文件.settings .project .classpath target等
eclipse svn提交忽略文件及文件夹,ignore设置无效.. 一.方法: 1. 将文件夹或文件从Eclipse中删除.记得要在Eclipse中删除,而不是Windows文件管理界面删除. 2. ...
- Luogu P1092 虫食算(枚举+剪枝)
P1092 虫食算 题面 题目描述 所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母.来看一个简单的例子: 43#9865#045 + 8468#6633 4 ...