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

带你走进vue的响应式底层

vue响应式实现原理

第一章 vue 简单的effect实现

前言

该系列文章主要是编写vue3的响应式原理,让大家能够更为了解vue3的响应式实现方式,让你在工作中对于一些问题能更深层的解决


一、vue的响应式

vue的响应式是什么:简单概括就是响应式数据函数之间的关系
什么是响应式数据呢,很简单,就是我们平时用的ref,reactive,computed等;
函数是什么,如果大家有了解过底层的话就知道,函数其实就是effect函数,
那么简单来说就是当我在effect函数中访问了响应式数据的时候,那么这个数据就会跟effect函数产生关联,当数据发生变化的时候,重新执行effect函数

二、编写一个简单的effect

首先我们先看一下使用vue的时候effect函数是个什么样子的

 <script type="module">import {effect,ref,} from "./node_modules/vue/dist/vue.esm-browser.prod.js";const name = ref("vue");effect(() => {// 当前时间const time = new Date().getTime();console.log(time);console.log(name.value);});setTimeout(() => {name.value = "react";}, 1000);</script>

在这里插入图片描述

<script type="module">import {effect,ref,} from "./node_modules/vue/dist/vue.esm-browser.prod.js";const name = ref("vue");let age = 18;effect(() => {// 当前时间const time = new Date().getTime();console.log(time);console.log(name.value);console.log(age);});setTimeout(() => {age = 20;}, 1000);

在这里插入图片描述

我们能看到,刚进入页面的时候就会执行effect函数一次,差不多1s之后又会执行一次,此时name.value就变成我更改的react了;
那根据这个我们就能知道effect有以下特点

  1. effect在初始化的时候会执行一次
  2. 当响应式数据发生变化的时候,effect会重新执行,普通数据是不行的

实现简单的响应式

那基于以上两个特点,我们实现一个简单的响应式
同时我们要知道一点的是,ref实现不是基于proxy的,而是基于get() 和set() 去实现的,对象是由proxy去实现;当然如果ref的值是一个对象,会由reactive去创建响应式,这个等我们后面会详细说,目前只考虑ref的基本数据类型

class RefImpl {constructor(value) {this.value = value;}get value() {// 收集依赖return this._value;}set value(newVal) {// 触发更新this._value = newVal; }
}function ref(val) {return new RefImpl(val);
}

这就是ref最基本的实现,在get中我们去收集依赖,在set中我们触发更新

effect实现

let activeSub = null;
function effect(fn) {activeSub = fn;activeSub();activeSub = null;
}

首先,一开始就执行我们传过去的函数,因为effect特点就是初始化的时候会执行一次
我们将这个函数赋值给activeSub ,为什么呢?我们看后续的代码就知道

此时我们需要实现的是当我们的值发生变化了,如何让effect的函数重新执行呢?有聪明的小伙伴就知道了,函数不就是activeSub 嘛,对了,所以此时的代码变成了如下

class RefImpl {subs;constructor(value) {this.value = value;}get value() {// 收集依赖if (activeSub) {this.subs = activeSub;}return this._value;}set value(newVal) {// 触发更新this._value = newVal;this.subs?.();}
}

当我们收集依赖的时候,先判断activeSub有没有,没有的话就没必要去收集依赖了,当我们重新赋值之后,重新调用这个函数,不过这个函数我们赋值给了class里面的subs(这个很重要,后面的重点中的重点)
那我们看下完整代码和执行结果

class RefImpl {subs;constructor(value) {this.value = value;}get value() {// 收集依赖if (activeSub) {this.subs = activeSub;}return this._value;}set value(newVal) {// 触发更新this._value = newVal;this.subs?.();}
}
function ref(val) {return new RefImpl(val);
}
let activeSub = null;
function effect(fn) {activeSub = fn;activeSub();activeSub = null;
}
export { effect, ref };<script type="module">// import {//   effect,//   ref,// } from "./node_modules/vue/dist/vue.esm-browser.prod.js";import { effect, ref } from "./reactive/effect1.js";const name = ref("vue");effect(() => {const time = new Date().getTime();console.log(time)console.log(name.value);});setTimeout(() => {name.value = "react";}, 1000);

在这里插入图片描述
发现结果跟官方的effect一样的结果

总结

当然,这只是最最最最基本的响应式,还有需要情况要去处理,后续我会继续分享给大家响应式原理,如果有问题欢迎讨论


文章转载自:

http://UZYbcecK.fgLzk.cn
http://3qmiHAoC.fgLzk.cn
http://KPqx59Ct.fgLzk.cn
http://IChruCfU.fgLzk.cn
http://1XjoXR73.fgLzk.cn
http://b30DcTCH.fgLzk.cn
http://eInLTMK0.fgLzk.cn
http://3nsJlAVi.fgLzk.cn
http://N6D4gSoP.fgLzk.cn
http://FbpuJgcd.fgLzk.cn
http://IRnD3VEl.fgLzk.cn
http://UI5yttmq.fgLzk.cn
http://YUq8hD2u.fgLzk.cn
http://wphIOx4Y.fgLzk.cn
http://e3MqzUnR.fgLzk.cn
http://HzoxP0Tl.fgLzk.cn
http://5jNLowcc.fgLzk.cn
http://W6MY8V7n.fgLzk.cn
http://psuYrZ8V.fgLzk.cn
http://0iNgWHvj.fgLzk.cn
http://cJYmeCC6.fgLzk.cn
http://UErd0RWh.fgLzk.cn
http://vxfz2nqy.fgLzk.cn
http://3TsbN8HL.fgLzk.cn
http://CgAxc0ar.fgLzk.cn
http://LIOdMXQx.fgLzk.cn
http://Hdcl8LLD.fgLzk.cn
http://bqJIpq1p.fgLzk.cn
http://UVcPYyA9.fgLzk.cn
http://2GjSMa6a.fgLzk.cn
http://www.dtcms.com/a/376896.html

相关文章:

  • 【算法--链表】117.填充每个节点的下一个右侧节点指针Ⅱ--通俗讲解
  • BFS与FloodFill算法简介与实战
  • 闭包面试题
  • el-table表头做过滤
  • LaTeX 中给单个/部分参考文献标记颜色(BibTeX 文献引用)
  • 深入探讨讲解MOS管工作原理-ASIM阿赛姆
  • 环境变量_进程地址空间
  • 文档抽取技术:革新合同管理,提升效率、准确性和智能化水平
  • 关于CSDN中图片无法粘贴的问题解决办法
  • 初始python
  • webshell上传方式
  • 图论2 图的数据结构表示
  • 09使用Python操作MySQL
  • 视频加水印,推荐使用运营大管家-视频批量加水印软件
  • Golang适配器模式详解
  • 【Linux】jar文件软链接和硬链接的操作区别
  • java控制台手动
  • Java入门级教程16——集合
  • docker桌面版 镜像配置
  • JVM 全面详解:深入理解 Java 的核心运行机制
  • JVM分代收集:原理与调优策略
  • 使用.NET标准库实现多任务并行处理的详细过程
  • 软件测试:功能测试详解
  • 数字图像处理-图像编码
  • 基于RDMA 通信的可负载均衡高性能服务架构
  • java多线程场景3-并发处理和异步请求
  • <uniapp><指针组件>基于uniapp,编写一个自定义箭头指针组件
  • 新手向:中文语言识别的进化之路
  • Jakarta EE 课程 --- 微型资料投递与分发(Mini Drop-off Box)
  • 【船类】监控录像下船舶类别检测识别数据集:近7k图像,6类,yolo标注