带你手撕一个简易响应式副作用函数

前言

彦祖们,开发 vue3 的时候,我们肯定用过 watchEffect

官网解释:立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行。 第一个参数就是要运行的副作用函数

此时引入了副作用函数这个概念,那么到底什么是副作用函数呢?

什么是副作用函数?

其实副作用函数就是指会产生副作用的函数(...听君一席话,听君一席话)

言归正传,副作用函数其实就是除了本函数还有其他函数能修改本函数执行效果的函数

比如说,我们写一个函数,这个函数内部修改了 body 标签的 innerHTML

除了这个函数,其他函数也具备修改 body 标签的 innerHTML 能力

此时我们就把这个函数 effect 就是称为副作用函数

js 复制代码
function effect() {
  document.body.innerHTML = 'Hello Daniel Wu'
}

document.body.innerHTML = 'Hello Edision' // 外部可以修改 innerHTML

无副作用函数

相比副作用函数,我们再来看下无副作用函数

其实也很简单

js 复制代码
function sum(a, b) {
  return a + b
}

这个函数,我们只返回了 a + b 的结果,并不具备任何的副作用(其他外部函数无法影响这个函数的执行结果)

什么是响应式?

现在我们已经知道什么是副作用函数了,那么我们再来看下什么是响应式?

响应式就是指,当数据发生变化的时候,我们希望对应的副作用函数也能执行的过程

比如说

js 复制代码
const person = {name:'Daniel Wu',age:18}
function effect() {
  document.body.innerHTML = 'Hello ' + person.name
}
effect()

当我们修改 person.name 的时候,我们希望 effect 函数能够执行

当然最简单的方式就是手动执行

js 复制代码
person.name = 'Edison'
effect() // 手动执行副作用函数

此时 innerHTML 就变成下图所示

那么我们如何让 person.name 发生变化的时候,自动执行副作用函数呢?

实现响应式

响应式原理

其实思路也很简单,不就是监听 person.name 变化,然后执行副作用函数

监听 person.name 变化? 这不就是八股文中常考的 Proxy 拦截吗?

代码非常简单

js 复制代码
const person = {name:'Daniel Wu',age:18}

const proxyPerson = new Proxy(person,{
  // set 拦截器
  set(target,key,value) {
    target[key] = value
    effect() // 进入拦截器的时候执行 effect 函数
    return true
  }
})

获取到代理对象后,我们把之前的 person 都替换成代理对象 proxyPerson

完整代码

js 复制代码
const person = {name:'Daniel Wu',age:18}

const proxyPerson = new Proxy(person,{
  // set 拦截器
  set(target,key,value) {
    target[key] = value
    effect() // 进入拦截器的时候执行 effect 函数
    return true
  }
})
function effect() {
  document.body.innerHTML = 'Hello ' + proxyPerson.name
}

proxyPerson.name = 'Edison' // 此时进入 set 函数,自动修改了 innerHTML

总结

以上我们就实现了一个非常简单的响应式副作用函数

其核心就是利用 Proxy 实现 set 拦截,然后在拦截器内部执行副作用函数

下一节我们将学习做一个更通用 effect 函数

写在最后

感谢彦祖们的阅读

个人能力有限

如有不对,欢迎指正 🌟 如有帮助,建议小心心大拇指三连🌟

相关推荐
名字还没想好☜5 小时前
React 实现暗黑模式切换:localStorage 持久化、SSR 首屏闪烁与跟随系统主题
前端·javascript·react.js·ecmascript·react·next.js
自动化监测Learner6 小时前
主流 Web 端地图引擎对比:选型指南与优劣分析
javascript
console.log('npc')6 小时前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享7 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕8 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路8 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持8 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机毕设定制辅导-无忧学长8 小时前
《基于SpringBoot青年公寓出租管理系统的设计与实现》
java·vue.js·spring boot·青年公寓出租管理系统
计算机魔术师10 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy345310 小时前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计