摘要:响应式原理之不论如何,最终响应式数据都要通过来实现,实际要借助新增的。在函数内,首先实例化一个实例,会在稍后添加为响应式数据自定义的中发挥作用。只有数组和对象才可能是响应式,才能返回实例。参考链接技术内幕揭开数据响应系统的面纱源码
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。
参考链接Vue技术内幕|揭开数据响应系统的面纱
Vue.js源码
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/99627.html
摘要:响应式原理之之前简单介绍了和类的代码和作用,现在来介绍一下类和。对于数组,响应式的实现稍有不同。不存在时,说明不是响应式数据,直接更新。如果对象是响应式的,确保删除能触发更新视图。 Vue响应式原理之Observer 之前简单介绍了Dep和Watcher类的代码和作用,现在来介绍一下Observer类和set/get。在Vue实例后再添加响应式数据时需要借助Vue.set/vm.$se...
摘要:响应式原理为了探究这一切的原因,我再次点开了的官网。在官网很下面的位置,找到了关于响应式原理的说明。因此,新添加到数组中的对象中的属性,就成了非响应式的属性了,改变它自然不会让组件重新渲染。响应式属性的对象,有这个对象就代表是响应式的。 最近在用Vue开发一个后台管理的demo,有一个非常常规的需求。然而这个常规的需求中,包含了大量的知识点。有一个产品表格,用来显示不同产品的信息。...
摘要:浅析响应式原理一的特点之一是响应式,视图随着数据的更新而更新,在视图中修改数据后实例中的数据也会同步更新。对于每个响应式数据,会有两个实例,第一个是在中的闭包遍历,用途显而易见。接收一个回调函数,会在重新求值且值更新后执行。 浅析Vue响应式原理(一) Vue的特点之一是响应式,视图随着数据的更新而更新,在视图中修改数据后Vue实例中的数据也会同步更新。内部借助依赖(下文中的Dep类)...
摘要:哪吒别人的看法都是狗屁,你是谁只有你自己说了才算,这是爹教我的道理。哪吒去他个鸟命我命由我,不由天是魔是仙,我自己决定哪吒白白搭上一条人命,你傻不傻敖丙不傻谁和你做朋友太乙真人人是否能够改变命运,我不晓得。我只晓得,不认命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出处 查看github最新的Vue...
阅读 2164·2023-04-26 00:43
阅读 2685·2021-11-22 15:22
阅读 3816·2021-11-11 16:55
阅读 969·2021-11-04 16:06
阅读 1787·2019-08-30 14:12
阅读 999·2019-08-30 14:02
阅读 3368·2019-08-29 17:05
阅读 1417·2019-08-29 12:27