Vue3响应式原理实现与track和trigger依赖收集和触发依赖

前言

Vue的响应式系统是基于数据劫持加发布订阅者模式实现的,数据响应式就是建立响应式数据依赖的关系 (调用了响应式数据的操作之间的关系)
vue2使用Object.defineProperty进行数据拦截,而Vue3使用Proxy进行数据拦截是es6中新加的api,比Object.defineProperty解除了很多限制,性能更加优秀

Proxy

利用Proxy代理对象进行数据劫持

Proxy的基本使用
const testobj= { count: 0 };
const proxy = new Proxy(testobj, {
get(target, key) {
console.log('触发get')
return Reflect.get(target, key)
},
set(target, key, value) {
console.log('触发set')
return Reflect.set(target, key, value)
},
});
console.log(proxy.count) // 触发get
proxy.count = 1 // 触发set

在Vue3中,会通过拦截 getset 操作来实现依赖收集和触发依赖。当我们访问响应式对象的属性时,会触发 get 操作,此时 Vue3 会将当前的依赖(effect)项添加到依赖列表中;当我们修改响应式对象的属性时,会触发 set 操作,此时 Vue3 会遍历依赖列表,调用每个依赖项的更新函数,对视图进行更新。

所以先定义依赖类,需要有数据结构来存储依赖,
effect副作用函数,这个函数在响应式数据发生变化时会被自动触发,从而执行相关的操作。可以完善effect副作用函数来控制响应式数据
// 定义的依赖类
class ReactiveEffect{
	private _fn_;
	constructor(fn){
		this._fn_ = fn
	}
	run(){
		activeEffect = this
		this._fn_()
	}
}
let activeEffect;
//effect副函数
//传入一个直接执行的函数
function effect(fn){
	const _effect = new ReactiveEffect(fn)
	_effect.run()
}

当访问响应式对象的属性时,会添加一个依赖项,并将当前的 activeEffect 类保存到一个 effects 集合中,而 effects 集合则以 target 对象为键,以保存在该对象上的依赖项的列表为值。这也就是track收集依赖

为什么用WeakMap做数据结构呢?weakMap重要在它的弱字,WeakMap 中的键是弱引用的,意味着,当键不再被其他地方引用时,垃圾回收器可以自动清除这些键对应的值。可以优化性能
const targetMap = new WeakMap()

//收集依赖

function track(target, key) {

let depsMap = targetMap.get(target)

if (!depsMap) {

depsMap = new Map()

targetMap.set(target, depsMap)

}

let dep = depsMap.get(key);

if (!dep) {

dep = new Set()

depsMap.set(key, dep)

}

dep.add(activeEffect)
}
//简化下代码
function track(target, key) {

const depsMap = targetMap.get(target) || new Map();

targetMap.set(target, depsMap);

const dep = depsMap.get(key) || new Set();

depsMap.set(key, dep);

dep.add(activeEffect);

}
trigger触发依赖是当响应式对象属性修改时,系统会遍历依赖项列表,逐个执行保存在其中的 activeEffect 类,代表了对应依赖项的操作。
function trigger(target,key) {

const depsMap = targetMap.get(target)

const deps = depsMap.get(key)

for(const effect of deps){

effect.run()

}
}
这下可以根据上述实现一波reactive实现
let activeEffect;
function isObject(raw) {
if (raw === null) {
return false
} else if (typeof raw === 'object' || typeof raw === 'function') {
return true
} else {
return false
}
}
function reactive(raw){
	if (!isObject(raw)) {
	console.warn(`${raw} not object`)
	return raw
	}
	return new Proxy(raw,{
	get(target, key) {
		const res =Reflect.get(target, key)
		track(target,key)
		return res
	},
	set(target,key,value){
		const res = Reflect.set(target, key, value)
		trigger(target,key,value)
		return res //这是个布尔值
	}		
	})
}
//实现依赖类和effect函数
class ReactiveEffect{

_fn_;

constructor(fn){

this._fn_ = fn

}

run(){

activeEffect = this;

this._fn_();

}

}

function effect(fn){

const _effect = new ReactiveEffect(fn)

_effect.run()

}
const targetMap = new WeakMap()

//收集依赖
function track(target, key) {

let depsMap = targetMap.get(target)

if (!depsMap) {

depsMap = new Map()

targetMap.set(target, depsMap)

}

let dep = depsMap.get(key);

if (!dep) {

dep = new Set()

depsMap.set(key, dep)

}

dep.add(activeEffect)

}

//触发依赖
function trigger(target,key) {

const depsMap = targetMap.get(target)

const deps = depsMap.get(key)

for(const effect of deps){

effect.run()
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/601704.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

普通人适合做大模型吗?过程中会发生什么潜在的挑战?

对于普通人来说,直接进行大模型的研发和训练可能存在一定的挑战,因为这通常需要以下资源和知识: 专业知识: 大模型的开发需要深入理解机器学习、深度学习、神经网络等领域的知识。 计算资源: 大模型的训练需要高性能的…

数组元素翻倍C++

编写一个 C 程序&#xff0c;实现一个功能&#xff0c;即将数组中的每个元素值翻倍。程序应定义一个函数 doubleArray&#xff0c;该函数接收一个整数数组的指针和数组的大小&#xff0c;然后将数组中的每个元素都翻倍。 代码 #include <iostream>void doubleArray(int…

JSON++介绍

1.简介 JSON 是一个轻量级的 JSON 解析库&#xff0c;它是 JSON&#xff08;JavaScript Object Notation&#xff09;的一个超集。整个代码由一个单独的头文件json.hpp组成&#xff0c;没有库&#xff0c;没有子项目&#xff0c;没有依赖项&#xff0c;没有复杂的构建系统&…

安防视频/视频汇聚系统EasyCVR视频融合云平台助力智能化酒店安防体系的搭建

一、背景需求 2024年“五一”假期&#xff0c;全国文化和旅游市场总体平稳有序。文化和旅游部6日发布数据显示&#xff0c;据文化和旅游部数据中心测算&#xff0c;全国国内旅游出游合计2.95亿人次。“五一”假期县域市场酒店预订订单同比增长68%&#xff0c;而酒店作为一个高…

js原生手写一个拖拽小功能

先上效果图 附上代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><meta name"viewport" content"widthd…

check startup检查各种资源文件

check startup 命令功能 check startup命令用来检查各种资源文件&#xff08;paf文件、补丁包、启动软件、配置文件&#xff09;是否正确。 命令格式 check startup [ crc ] [ next ] 参数说明 参数参数说明取值 crc 对资源文件进行CRC校验。 - next 检查下一次启动的各…

Git系列:Git Switch 高效使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

用标准的GNU/Linux命令替换Alpine上的精简版命令

Alpine Linux 是一个基于 musl libc 和 busybox 的轻量级Linux发行版&#xff0c;busybox 实现了很多常用类Unix命令的精简版&#xff0c;特点是体积很小&#xff0c;舍弃了很多不常用参数&#xff0c;我们简单对比一下标准Linux自带的 date 命令 和 Alpine下默认的 date 命令便…

Golang | Leetcode Golang题解之第76题最小覆盖子串

题目&#xff1a; 题解&#xff1a; func minWindow(s string, t string) string {ori, cnt : map[byte]int{}, map[byte]int{}for i : 0; i < len(t); i {ori[t[i]]}sLen : len(s)len : math.MaxInt32ansL, ansR : -1, -1check : func() bool {for k, v : range ori {if c…

每日两题 / 138. 随机链表的复制 148. 排序链表(LeetCode热题100)

138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 用哈希表记录原链表中的节点是否被复制过 遍历原链表并通过哈希表维护新链表 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;rand…

Glowroot:Java应用的性能守护神,让监控变得既轻松又有趣!

Glowroot&#xff1a;Java应用的性能守护神&#xff0c;让监控变得既轻松又有趣&#xff01; 在这个快节奏的数字化时代&#xff0c;作为一名开发者&#xff0c;你是否曾因应用性能问题而夜不能寐&#xff1f;是不是常幻想有个超级英雄能在关键时刻挺身而出&#xff0c;帮你揪…

淘宝优惠券领取软件草柴返利APP想从淘宝粘贴提示怎么关闭?想从天猫粘贴、想从京东粘贴弹窗提示关闭

使用iPhone苹果手机想从淘宝点击分享复制链接&#xff0c;到草柴APP查询该商品内部大额隐藏优惠券和返利。可是&#xff0c;苹果iPhone手机每次将复制的商品链接&#xff0c;粘贴到草柴APP时都是提示&#xff1a;“草柴”想从“淘宝”粘贴&#xff0c;每次都需要点击允许粘贴后…

docker搭建代码审计平台sonarqube

docker搭建代码审计平台sonarqube 一、代码审计关注的质量指标二、静态分析技术分类三、sonarqube流程四、快速搭建sonarqube五、sonarqube scanner的安装和使用 一、代码审计关注的质量指标 代码坏味道 代码规范技术债评估 bug和漏洞代码重复度单测与集成 测试用例数量覆盖率…

管易云与金蝶K3-WISE对接集成发货单查询2.0打通新增销售出库(红蓝字)

管易云与金蝶K3-WISE对接集成发货单查询2.0打通新增销售出库&#xff08;红蓝字&#xff09; 源系统:管易云 金蝶管易云是金蝶集团旗下以电商和新零售为核心业务的子公司&#xff0c;公司于2008年成立&#xff0c;拥有从事电商及新零售业务相关专业知识工作者超过1000人。为伊利…

35道必懂的 Linux 运维面试题

1、现在给你三百台服务器&#xff0c;你怎么对他们进行管理&#xff1f; 管理3百台服务器的方式&#xff1a; 1&#xff09;设定跳板机&#xff0c;使用统一账号登录&#xff0c;便于安全与登录的考量。 2&#xff09;使用 salt、ansiable、puppet 进行系统的统一调度与配置的…

鸿蒙 DevEcoStudio:简单实现网络请求登录案例

使用http或axios实现登录案例 在entry/src/main/ets/pages路径下新建Page9.ets文件&#xff1a; import http from ohos.net.http import router from ohos.router Entry Component struct Page9 {State message: string Hello WorldState username: string State password:…

【网络原理】HTTP协议 | 报文格式 | Fiddler抓包 | HTTP请求 | HTTP响应 | 构造HTTP请求

文章目录 HTTP协议使用HTTP的场景&#xff1a; 一、HTTP协议的报文格式1.Fiddler的使用教程 二、HTTP请求(Request)1.首行&#xff1a;1)方法(method)GET和POST的区别(面试题) 2)URL 2.请求头&#xff08;header&#xff09;&#xff1a;1.HOST:2.Content-Length3.body中数据的…

个人IP打造孵化运营产业链商业计划书

【干货资料持续更新&#xff0c;以防走丢】 个人IP打造孵化运营产业链商业计划书 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 PPT共90页&#xff08;完整资料包含以下内容&#xff09; 目录 个人IP运营方案&#xff1a; 1. 个人IP定位与构建 1.1 人格画像构…

2024五一档中国电影市场研究报告

来源&#xff1a;拓普数据 2024年五一档内地电影总票房15.27亿&#xff0c;同比增长0.38%&#xff0c;低于2021年的16.74亿&#xff0c;与2019年档期票房相当。日均大盘票房3.05亿&#xff0c;同比小幅增长0.4%&#xff0c;低于2018-2021年同期&#xff0c;位居档期影史第四。…

列表处理基础问题的四种方法:从入门到惊艳

目录 一、引言 二、方法一&#xff1a;基础循环遍历 三、方法二&#xff1a;列表推导式 四、方法三&#xff1a;内置函数与高阶函数 五、方法四&#xff1a;惊艳的库与工具 六、案例研究 七、总结 一、引言 在编程的世界中&#xff0c;列表&#xff08;List&#xff09…
最新文章