Vue 2 阅读理解(十五)之响应式系统(一)Object.defineProperty

简介: Vue 2 阅读理解(十五)之响应式系统(一)Object.defineProperty

响应式系统(一)


在 Vue 2 的官方文档 - 深入响应式原理 中介绍了 Vue 最独特的特性就是 非侵入性 的响应式系统,所有的数据模型都是对象形式。


在 Vue 2 中,每个 Vue 实例都接收一个 对象形式 Options 来初始化,并通过 Object.defineProperty 来对象里面的一些属性的 默认getter/setter 方法全部转化为 特殊的会触发依赖收集的 getter/setter 方法


1. 变化追踪过程


官方给出的回答是:每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。


网络异常,图片无法展示
|


2. re-render 与渲染 Watcher


上面的 每一个组件实例都对应的 Watcher 实例,通常我们称为 渲染 Watcher,在 $mount() 首次执行挂载时初始化。


渲染 Watcher 实例配置了一个 执行前函数 watcherOptions.before 和一个执行 watcher.run() 时执行的 回调函数 cb


watcherOptions.before 主要只有一行内容:


if (vm._isMounted && !vm._isDestroyed) {
  callHook(vm, 'beforeUpdate')
}


即在更新前会触发 beforeUpdate 生命周期钩子,执行配置的相关方法。

回调函数 cb 一样只有一点内容:


updateComponent = () => {
  vm._update(vm._render(), hydrating)
}


即用来更新 dom 内容(当然开发环境如果开启了性能分析的话,这里还有其他的处理)


这个过程即是上图的 re-render 过程: Watcher ==> Component Render Function


3. getter 与 setter


上面已经说了 wachter 在变化触发时会执行 vm._update()callHook('beforeUpdate'),而 getter/setter 是如何定义和触发更新的呢?


const property = Object.getOwnPropertyDescriptor(obj, key)  
const getter = property && property.get
const setter = property && property.set
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()
                isArray(value) && dependArray(value)
            }
        }
        return isRef(value) && !shallow ? value.value : value
    },
    set: function reactiveSetter(newVal) {
        const value = getter ? getter.call(obj) : val
        if (!hasChanged(value, newVal)) {
            return
        }
        if (setter) {
            setter.call(obj, newVal)
        } else if (getter) {
            return
        } else if (!shallow && isRef(value) && !isRef(newVal)) {
            value.value = newVal
            return
        } else {
            val = newVal
        }
        childOb = !shallow && observe(newVal, false, mock)
        dep.notify()
    }
})


这里首先是 将对象的 默认 get 和 set 方法保存下来,通过 Object.defineProperty 重新定义该对象每个属性的 get 和 set 方法


get:


首先直接通过 默认 get 获取到值,并且如果这个值是个对象或者数组的话,还会进行深层次遍历,最后返回该属性的值。


当然这里为了兼容 v3 语法,新增了一个 isRef 的判断,用来处理 ref 定义的变量;在以前的版本都是直接返回 value 的。


set


作为重设对象属性值的方法,为了避免多次更新相同属性值,这里会在最前面增加一个 hasChanged(value, newVal) 的判断,如果多次更新的值一样,则不会重复设置和触发更新。


然后便是属性的更新:


  • 对于具有默认 setter 的属性(即在初始化时就定义了的对象属性),会直接调用默认 set 方法


  • 如果只有默认 getter 方法,说明该属性不能更新,则直接退出


  • 以上都不满足,则直接更新属性值为 newVal


最后一样会处理对象子属性,并通过 dep.notify() 来触发依赖该对象的 watcher 的更新。因为组件渲染 watcher 算是默认的watcher,所以如果该属性更新影响到了页面效果,则会触发视图更新。


相关文章
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
99 13
【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
83 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
69 11
【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
86 13
【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
Vue是如何劫持响应式对象的
Vue是如何劫持响应式对象的
76 18
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
126 17
介绍一下Vue中的响应式原理
介绍一下Vue中的响应式原理
66 1
深度剖析 Vue.js 响应式原理:从数据劫持到视图更新的全流程详解
本文深入解析Vue.js的响应式机制,从数据劫持到视图更新的全过程,详细讲解了其实现原理和运作流程。
|
5月前
|
API
vue3知识点:响应式数据的判断
vue3知识点:响应式数据的判断
44 3
优化Vue的响应式性能
【10月更文挑战第13天】优化 Vue 的响应式性能是一个持续的过程,需要不断地探索和实践,以适应不断变化的应用需求和性能挑战。
61 2

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等