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,所以如果该属性更新影响到了页面效果,则会触发视图更新。


目录
相关文章
|
2天前
|
JavaScript 前端开发
深入了解前端框架Vue.js的响应式原理
本文将深入探讨Vue.js前端框架的核心特性之一——响应式原理。通过分析Vue.js中的数据绑定、依赖追踪和虚拟DOM等机制,读者将对Vue.js的响应式系统有更深入的理解,从而能够更好地利用Vue.js构建灵活、高效的前端应用。
|
2天前
|
JavaScript 测试技术 开发者
Vue 3 Vuex:构建更强大的状态管理系统
Vue 3 Vuex:构建更强大的状态管理系统
25 1
|
2天前
|
JavaScript
vue2中$set的原理_它对object属性做了啥?
vue2中$set的原理_它对object属性做了啥?
11 1
|
2天前
|
JavaScript 前端开发 开发者
Vue的响应式原理:深入探索Vue的响应式系统与依赖追踪
【4月更文挑战第24天】Vue的响应式原理通过JavaScript getter/setter实现,当数据变化时自动更新视图。它创建Watcher对象收集依赖,并通过依赖追踪机制精确通知更新。当属性改变,setter触发更新相关Watcher,重新执行操作以反映数据最新状态。Vue的响应式系统结合依赖追踪,有效提高性能,简化复杂应用的开发,但对某些复杂数据结构需额外处理。
|
2天前
|
JavaScript 前端开发 UED
Vue工具和生态系统: Vue.js和服务器端渲染(SSR)有关系吗?请解释。
Vue.js是一个渐进式JavaScript框架,常用于开发单页面应用,但其首屏加载较慢影响用户体验和SEO。为解决此问题,Vue.js支持服务器端渲染(SSR),在服务器预生成HTML,加快首屏速度。Vue.js的SSR可手动实现或借助如Nuxt.js的第三方库简化流程。Nuxt.js是基于Vue.js的服务器端渲染框架,整合核心库并提供额外功能,帮助构建高效的应用,改善用户体验。
21 0
|
2天前
|
JavaScript 搜索推荐 前端开发
Vue工具和生态系统:Vue CLI是什么?它的作用是什么?
【4月更文挑战第17天】Vue CLI是官方的Vue.js开发加速器,它包含交互式项目模板和@vue/cli-service,基于webpack并预设配置。支持个性化配置和插件扩展,拥有大量官方插件,整合最佳前端工具。还提供图形化界面用于项目管理和创建。
11 0
|
2天前
|
Web App开发 JavaScript 开发者
Vue工具和生态系统:什么是Vue DevTools?如何使用它?
Vue Devtools是Vue.js官方的浏览器扩展,用于简化应用调试和优化。可在Chrome和Firefox等浏览器上安装,集成到开发者工具中。安装步骤包括下载源码、npm安装、修改manifest.json并加载编译后的扩展。启用后,开发者能查看Vue组件树,检查属性,并在允许的情况下编辑data,提升开发效率。
18 0
|
2天前
|
JavaScript 前端开发 开发者
浅谈Vue 3的响应式对象: ref和reactive
浅谈Vue 3的响应式对象: ref和reactive
|
2天前
Vue3 响应式数据 reactive使用
Vue3 响应式数据 reactive使用
|
2天前
|
JavaScript
Vue 响应式数据的判断
Vue 响应式数据的判断