Vue.js 3 渐进式实现之响应式系统——第一节:系列开篇与响应式基本实现

为什么做这个系列

谈到 Vue.js 这个框架,其本身最广为人知的特性,同时也是与日常开发关系最密切、求职面试考察最多的,一定是响应式系统。因此深入理解响应式系统的实现原理对每个使用 Vue 的开发者来说都是十分必要的。

学习原理最好的方式是什么?自己从 0 开始手写实现一遍,由此得来的理解的一定是最准确的并且记忆最深刻

渐进式实现

Vue 官方文档首页就声明了,它是一个渐进式框架。意思是新手不必一上来就使用框架提供的所有特性,而是可以由浅到深逐步集成,因此学习曲线非常平滑。

学习原理也是一样的道理,一上来就理解并实现所有功能对绝大部分人来说都是不现实的。此时也可以借鉴"渐进式"的思路,从最最基础的实现开始,一步步迭代增加新功能,逐步完善,最终得到完整实现

因此我决定开始《Vue.js 3 渐进式实现》 这一系列,手把手带大家从 0 开始一步步实现 Vue 的主要功能模块,从响应式系统开始。记录我自己学习过程的同时也由衷希望能帮助到更多的人。

适合阅读人群

不需要看过一行的源码,只要你有一定的 Vue 使用基础,都可以跟随本系列深入学习原理。学完之后,相信日常工作和面试中遇到的90%关于 Vue 的问题对你来说都不将是问题。

响应式数据的基本实现

响应式原理是数据与函数的关联:当数据变化时,依赖了数据的函数自动重新运行

一个响应式系统的工作流程如下:

  • 读取操作发生时,将副作用函数收集到"桶"中;
  • 设置操作发生时,从"桶"中取出副作用函数并执行。

思路

为了实现这一点,我们需要拦截对数据的读和写。由于 JavaScript 中没有任何方式能拦截对原始值的读写,因此响应式数据只能是对象

Vue 2 中,为了兼容 IE,使用 ES5 的 Object.defineProperty函数实现,这种方式有不能拦截对象属性的增删以及无法拦截通过数组索引访问等缺点。

Vue 3 使用了 ES6 新增的 Proxy 实现响应式系统。Proxy 是一个构造函数,可以生成源对象的代理对象,拦截对源对象的操作,并且可以完全拦截 13 种对象的基本操作

代码

javascript 复制代码
// 原始数据
const data = { text: 'hellow world' }

function effect() {
    // effect 函数的执行会读取 data.text
    console.log(obj.text)
}

// 存储副作用函数的桶
const bucket = new Set()

// 对原始数据的代理
const obj = new Proxy(data, {
    // 拦截读取操作
    get(target, key) {
        // 将副作用函数 effect 添加到存储副作用的桶中
        bucket.add(effect)
        // 返回属性值
        return target[key]
    },
    // 拦截设置操作
    set(target, key, newVal) {
        // 设置属性值
        target[key] = newVal
        // 把副作用函数从桶里取出并执行
        bucket.forEach(fn => fn())
        // 返回 true 代表设置操作成功
        return true
    }
})

已实现

我们使用 Proxy 代理源对象,拦截对源对象的操作:

  1. 当读取属性时,将副作用函数 effect 添加到桶里,再返回属性值
  2. 当设置属性时,先更新原始数据,再将副作用函数从桶里取出并重新执行

缺陷/待实现

目前我们直接通过名字 "effect" 来获取副作用函数。这种硬编码的方式很不灵活,因为副作用函数的名字可以任意取,甚至是匿名函数。下一节我们将解决这个问题。

结语

本系列将一步步渐进式地实现 Vue 主要模块,从响应式系统开始。帮助大家深入理解原理的同时也是记录作者自己的学习过程。

响应式系统的第一节中,我们使用 Proxy 拦截对象属性的读和写,实现了当数据变化时,依赖了数据的函数自动重新运行。下一节中我们将解决硬编码副作用函数的问题。

相关推荐
徐小夕1 天前
我用 AI 撸了个开源"万能预览器":浏览器直接打开 Office、CAD 和 3D 模型
前端·vue.js·github
前端Hardy1 天前
字节/腾讯内部流出!Claude Code 2026王炸玩法!效率暴涨10倍
前端·javascript·vue.js
逆光如雪1 天前
移动端卡片边框怎么做高级?我用 CSS 实现了设计师的刁钻要求
前端·css·vue.js
莹宝思密达1 天前
地图显示西安经济开发区边界线-2023.12
前端·vue.js·数据可视化
leafyyuki1 天前
告别 Vuex 的繁琐!Pinia 如何以更优雅的方式重塑 Vue 状态管理
前端·javascript·vue.js
Hooray1 天前
AI 时代的管理后台框架,应该是什么样子?
前端·vue.js·ai编程
代码煮茶2 天前
Vue3 虚拟列表实战 | 解决长列表性能问题(十万条数据流畅渲染,附原理)
前端·javascript·vue.js
计算机学姐2 天前
基于SpringBoot的宠物店管理系统
java·vue.js·spring boot·后端·spring·java-ee·intellij-idea
布局呆星2 天前
Vue3 —— 监听器 (watch/watchEffect) 与 Props 组件通信
vue.js·笔记·学习
橘子编程2 天前
UniApp跨端开发终极指南
开发语言·vue.js·uni-app