vue2源码分析- 数据响应简单模拟
工作中大部分项目使用vue2做,但一直局限于使用,终于有闲暇时间可以学习下源码,网上优秀的源码分析很多,此文章只是记录个人所学,有问题欢迎大家指出,欢迎讨论,互相学习。
下面是我对vue2响应式数据的简单模拟,还需要亿点点补充。
vue2响应式数据原理主要通过 Object.defineProperty 数据劫持,当数据改变时,通过get方法注入依赖函数,set方执行依赖函数。
模拟效果:改变data里面的属性值后,该属性的依赖函数也会执行一次。
创建一个Dep类,Dep有一个静态值target 表示当前正在执行的函数, data里面的每个属性都有一个dep实例,dep 实例 中sub存储每个属性的依赖函数,addSub方法添加依赖函数,notify方法执行依赖函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | export default class Dep { static target = null ; // 全局正在执行的函数 constructor() {<em id= "__mceDel" > } addSub(sub) { // 存储在当前实例中正在执行的函数 this .sub.push(sub); } notify() { // 循环执行依赖的函数 this .sub.map((item) => item.update()); } } </em> |
this.sub = []; // 存储依赖的函数
数据响应式,遍历data,将每个属性都变成响应式,每个属性都初始化一个dep实例,当获取属性时触发get方法,收集该属性的依赖函数,修改属性值时触发set方法,执行依赖函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | import Dep from "./dep" ; function defineReactive(obj, key, val) { // 获取当前属性有没有自定义方法; let property = Object.getOwnPropertyDescriptor(obj, key); // 判断当前属性有没有自定义get set 方法 let getter = property && property.get; let setter = property && property.set; // 没有val值,去obj里面的 if ((!getter || setter) && arguments.length == 2) { val = obj[key]; } const dep = new Dep(); Object.defineProperty(obj, key, { enumerable: true , configurable: true , get: function () { //添加依赖函数 if (Dep.target) { dep.addSub(Dep.target); } //如果有自定义方法则调用 let value = getter ? getter.call(obj) : val; return value; }, set: function (newVal) { if (setter) { setter.call(obj, newVal); } else { val = newVal; } //执行依赖当前属性的依赖函数 dep.notify(); }, }); } function observer(data) { let keys = Object.keys(data); for ( let key of keys) { defineReactive(data, key); } } export { observer }; |
创建Watcher 类,将依赖函数实例为一个Watcher对象,在dep实例中sub 存储的不是依赖函数,而是Watcher实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import Dep from "./dep" ; export class Watcher { constructor(sub) { this .getter = sub; // 当前执行的函数 this .get(); } get() { Dep.target = this ; this .getter.call(); // 执行函数 } // 触发函数方法 update() { this .get(); } } |
效果展示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { observer } from "./observer" ; import { Watcher } from "./watcher" ; const data = { test: "aa" , test1: "cc" , }; const updateData = () => { console.log(data.test, "测试" ); }; //Object.defineProperty 劫持数据 将数据变成响应式 observer(data); // 注入依赖函数 new Watcher(updateData); data.test = "bb" ; |
分类:
vue
, vue / vue2源码学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具