vue3响应式原理(小满zs vue3 笔记八)
tip: 带着问题去理解响应式原理why,what,how
一. 响应式原理核心点是什么?
1 2 3 | ** 数据截持 ** ** 依赖收集 ** ** 派发更新 ** |
二.vue2的响应式原理? vue3响应式原理?区别是什么?
1. 下面vue2是官网上的这图片
1 2 3 4 5 | ** 通过 Object.defineProperty 遍历对象的每一个属性,把每一个属性变成一个 getter 和 setter 函数,读取属性的时候调用 getter, 给属性赋值的时候就会调用 setter.** ** 当运行 render 函数的时候,发现用到了响应式数据,这时候就会运行 getter 函数,然后 watcher(发布订阅)就会记录下来。 当响应式数据发生变化的时候,就会调用 setter 函数,watcher 就会再记录下来这次的变化,然后通知 render 函数, 数据发生了变化,然后就会重新运行 render 函数,重新生成虚拟 dom 树。 ** |
下面是具体的调度图
render -> watcher ($get 收集依赖, $set方法 派发更新), 执行Scheduler 调度队列里数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | vue2响应式原理总结: 1. 数据截持, vue2是通过Object.defineProperty来将对象的每一个属性转化成get,set; 其中修改对象的属性时就会触发set,使用对象的属性时就会触发get; 2. 依赖收集, 就是在渲染视图时,将watcher和具体的属性,通过发布订阅者模式管理,这样数据改变之后就能更精准的更新视图; 3. 派发更新, 它就是通过dep来执行watcher的notify方法. ** 使用Object.defineProperty做响应式的缺点 ** 1. 深度监听,需要一次性递归到底,计算量比较大; 2. 描述符只有get和set,无法监听新增属性和删除属性的操作; 3. 无法原生监听数组 这三个缺点中,第二点是defineProperty本身API的缺陷,而第一点和第三点都是出于性能考虑而做的取舍; ** 解决缺点的方法 ** 当我们通过数组的方法去更改数组时或是直接删除data数据,数据并不能实现响应式,因为Object.defineProperty是没有办法处理属性删除和新增的 因此vue2的响应式,通过数组方法(prop,push),或是删除,vue是不能监听的 vue2中通过vue2中可以通过vue.Delete和vue.Set这些vue内置api来改变属性,实现响应式。 |
2.0的不足
对象只能劫持 设置好的数据,新增的数据需要Vue.Set(xxx) 数组只能操作,修改某一项值无法劫持。数组的length修改也无法劫持
2. vue3 响应式原理(需要通过tsc把.ts变成js,目前index.html无内容待更新)
index.html
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 | <!DOCTYPE html> <html lang= "en" > <head> <meta charset= "UTF-8" > <meta http-equiv= "X-UA-Compatible" content= "IE=edge" > <meta name= "viewport" content= "width=device-width, initial-scale=1.0" > <title>Document</title> </head> <body> <div id= "app" > </div> <script type= "module" > import { reactive } from './reactive.js' import { effect } from './effet.js' const user = reactive({ name: "小满" , age: 18 }) effect(() => { document.querySelector( '#app' ).innerText = `${user.name} - ${user.age}` }) setTimeout(()=>{ user.name = '大满很吊' setTimeout(()=>{ user.age = '23' },1000) },2000) </script> </body> </html> |
reactive.ts
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 | import { track, trigger } from './effet' // 递归实现reactive const isObject = (target) => target != null && typeof target == 'object' // Vue3 的响应式原理依赖了 Proxy 这个核心 API,通过 Proxy 可以劫持对象的某些操作。 export const reactive = <T extends object>(target: T) => { // 第一个参数target return new Proxy(target, { // 第二个参数拦截器, target当前对象,key对象属性,reactive也是当前对象 get(target, key, receiver) { // Reflect保证上下文正确取值 const res = Reflect.get(target, key, receiver) as object // 收集依赖 track(target, key) if (isObject(res)) { return reactive(res) } return res }, // Reflect.set返回的是布尔值 set(target, key, value, receiver) { const res = Reflect.set(target, key, value, receiver) trigger(target, key) return res } }) } |
effet.ts
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 | // effect track trigger, 实现effect 副作用函数 // 使用一个全局变量 active 收集当前副作用函数,并且初始化的时候调用一下 let activeEffect: any; export const effect = (fn:Function) => { const _effect = function () { activeEffect = _effect; fn() } _effect() } // 实现track,收集依赖 const targetMap = new WeakMap() export const track = (target: any,key: any) =>{ let depsMap = targetMap.get(target) if (!depsMap){ // 第一次无值,对应value是一个Map depsMap = new Map() targetMap.set(target,depsMap) } // 对象取value let deps = depsMap.get(key) if (!deps){ deps = new Set() depsMap.set(key,deps) } // 收集副作用依赖 deps.add(activeEffect) } // 触发依赖 export const trigger = (target: any,key: any) => { const depsMap = targetMap.get(target) const deps = depsMap.get(key) deps.forEach(effect=>effect()) } |
参考文章 :
vue2
https://blog.csdn.net/m0_54581080/article/details/126036155
https://blog.csdn.net/weixin_71718397/article/details/125859350
vue3 是blibli小满视频vue3及csdn
将来的自己,会感谢现在不放弃的自己!
标签:
vue3
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
2018-07-13 UIView设置部分圆角---iOS开发UI篇