当前位置: 首页 > news >正文

Vue3源码reactivity响应式篇之reactive响应式对象的track与trigger

概览

BaseReactiveHandler类的get方法中,有如下代码块if (!isReadonly2){track(target, "get", key);},这表示通过reactiveshallowReactive创建的响应式对象,非只读的,当读取代理对象proxyTarget的某个属性key时,都会被该get方法拦截,即调用track()方法建立依赖。

而当对代理对象proxyTarget进行赋值或更新某个属性的值时,会被set方法拦截,即调用trigger()方法触发依赖(而删除会被deleteProperty拦截)。

因此对于reactive响应式对象的响应式处理,和tracktrigger方法密不可分。

本文主要介绍tracktrigger是如何进行依赖的收集与触发的全流程。
在这里插入图片描述

源码分析

在vue3中,维护了一个全局的targetMap WeakMap实例对象,用于存储响应式对象与依赖的映射关系。

const targetMap = new WeakMap();

track方法

track方法收集依赖就是往变量targetMap中添加相关元素,存储响应式对象与依赖的映射关系。

track的源码实现如下:

function track(target, type, key) {if (shouldTrack && activeSub) {let depsMap = targetMap.get(target);if (!depsMap) {targetMap.set(target, depsMap = new Map());}let dep = depsMap.get(key);if (!dep) {depsMap.set(key, dep = new Dep());dep.map = depsMap;dep.key = key;}dep.track();}
}

这里暂且不论shouldTrackactiveSub,假定满足track的条件。首先从targetMap中读取depsMap,若depsMap中不存在,则创建一个新的Map的实例,并将其赋值给depsMap,并且存储到targetMap中。然后从depsMap中获取key对应的依赖关系dep,同理,若dep不存在,则创建一个新的Dep实例,并将其赋值给dep,并且存储到depsMap中,然后将depmapkey分别绑定depsMapkey。最后调用dep.track()方法。

dep.track()执行后,会将当前的activeSub添加到depsubs数组中。

trigger方法

track方法的源码实现如下:

function trigger(target, type, key, newValue, oldValue, oldTarget) {const depsMap = targetMap.get(target);if (!depsMap) {globalVersion++;return;}const run = (dep) => {if (dep) {dep.trigger();}};startBatch();if (type === "clear") {depsMap.forEach(run);} else {const targetIsArray = isArray(target);const isArrayIndex = targetIsArray && isIntegerKey(key);if (targetIsArray && key === "length") {const newLength = Number(newValue);depsMap.forEach((dep, key2) => {if (key2 === "length" || key2 === ARRAY_ITERATE_KEY || !isSymbol(key2) && key2 >= newLength) {run(dep);}});} else {if (key !== void 0 || depsMap.has(void 0)) {run(depsMap.get(key));}if (isArrayIndex) {run(depsMap.get(ARRAY_ITERATE_KEY));}switch (type) {case "add":if (!targetIsArray) {run(depsMap.get(ITERATE_KEY));if (isMap(target)) {run(depsMap.get(MAP_KEY_ITERATE_KEY));}} else if (isArrayIndex) {run(depsMap.get("length"));}break;case "delete":if (!targetIsArray) {run(depsMap.get(ITERATE_KEY));if (isMap(target)) {run(depsMap.get(MAP_KEY_ITERATE_KEY));}}break;case "set":if (isMap(target)) {run(depsMap.get(ITERATE_KEY));}break;}}}endBatch();
}

trigger方法在响应式数据发生变化后会被触发,vue3会先判断全局响应式集合对象targetMap中是否存在依赖对象depsMap,即是否有被追踪依赖,若不存在,则将globalVersion1,然后直接返回,没有下一步;定义run方法;调用startBatch方法,表示要进行批处理。判断type是否clear,是,则遍历依赖对象depsMap,执行run方法;否则判断target是否是数组,以及key是否数组的索引,然后根据typekey取出响应式数据对应的具体依赖,调用run方法;最后调用endBatch方法。


文章转载自:

http://y9Tun9iG.zwkpg.cn
http://VMJtirTd.zwkpg.cn
http://tTeE6Q5E.zwkpg.cn
http://hNJjUfbG.zwkpg.cn
http://19OFGMFE.zwkpg.cn
http://mDDMfjnN.zwkpg.cn
http://6oDWHeJU.zwkpg.cn
http://sUzm3dCS.zwkpg.cn
http://qV80VvZH.zwkpg.cn
http://vGXEowzd.zwkpg.cn
http://ZfiGgv57.zwkpg.cn
http://O17smkI4.zwkpg.cn
http://N7Av0qz9.zwkpg.cn
http://tC1Zdxfz.zwkpg.cn
http://zQ7akQHh.zwkpg.cn
http://aO0scc8Z.zwkpg.cn
http://OjGxroZd.zwkpg.cn
http://yslSecIX.zwkpg.cn
http://fs71FCKv.zwkpg.cn
http://wNXYMJUv.zwkpg.cn
http://2JAgWiFv.zwkpg.cn
http://Y0mohDAW.zwkpg.cn
http://vwP4bmwO.zwkpg.cn
http://arvzX7dz.zwkpg.cn
http://uqV3uXXv.zwkpg.cn
http://FA6yPQay.zwkpg.cn
http://WSm81MqC.zwkpg.cn
http://68EHwaRe.zwkpg.cn
http://RGi4AsT3.zwkpg.cn
http://yP1fh9m5.zwkpg.cn
http://www.dtcms.com/a/373418.html

相关文章:

  • GitHub高星标项目:基于大数据的心理健康分析系统Hadoop+Spark完整实现
  • Google Guice @Inject、@Inject、@Singleton等注解的用法
  • 【MATLAB组合导航代码,平面】CKF(容积卡尔曼滤波)作为融合方法,状态量8维,观测量4维,包含二维平面上的严格的INS推导。附完整代码
  • Go Style 代码风格规范
  • Java 16 中引入的 record的基本用法
  • uni-app iOS 性能监控全流程 多工具协作的实战优化指南
  • shell 中 expect 详解
  • 告别低效:构建健壮R爬虫的工程思维
  • Ubuntu中显示英伟达显卡的工具软件或者指令
  • 银行卡号识别案例
  • 【golang学习笔记 gin 】1.2 redis 的使用
  • AI提示词(Prompt)基础核心知识点
  • VTK开发笔记(五):示例Cone2,熟悉观察者模式,在Qt窗口中详解复现对应的Demo
  • Excel 表格 - Excel 减少干扰、专注于内容的查看方式
  • Vue3 + Ant Design Vue 全局配置中文指南
  • CSS in JS 的演进:Styled Components, Emotion 等的深度对比与技术选型指引
  • 哈士奇vs网易高级数仓:数据仓库的灵魂是模型、数据质量还是计算速度?| 易错题
  • Windows 命令行:cd 命令2,切换到多级子目录
  • C++ 8
  • GD32入门到实战45--LVGL开发(Code::Blocks)之创建控件
  • 算法题(202):乌龟棋
  • 国产化服务注册与发现工具nacos安装
  • WordPress 性能优化:从插件到 CDN 的全方位缓存设置指南
  • 所有微服务部署都使用一个git地址,并且通过docker部署各个服务的情况下,如何编写mvn指令来处理各个服务。
  • 【AI】乡村振兴计划书:AI智能农业与设备研发销售一体化项目
  • 408 Request Timeout:请求超时,服务器等待客户端发送请求的时间过长。
  • 从车辆中心到用户中心:E/E架构的变革与挑战
  • 基于Mysql+SpringBoot+vue框架-校园商铺管理系统源码
  • SQL MERGE语句实战:高效增量数据处理
  • AI 云再进化,百度智能云新技术与产品全景解读