函数的副作用指什么(副作用函数与响应式数据的关系)

什么是副作用函数?

副作用函数就是在完成当前函数计算逻辑后,对外部数据也会产生影响的函数。
在计算机开发语言中「副作用函数」是个贬义词,副作用函数会对程序设计带来不必要的麻烦,还会增加难以查找的错误。
而在 Vue 和 React 框架中副作用函数被使用的淋漓尽致,虽然有时也会造成数据响应的心智成本(到底哪块数据变化了?),副作用函数自动渲染页面大大降低了我们的开发成本,这两个成本相对比起来说,毫无疑问开发成本是优先需要被降低的。
我们如何把下面的代码变成副作用函数自动渲染的?
const obj = {    text: \\\'hello world\\\'}//副作用函数function effect() {    // effect 函数的执行,会读取 obj.text 的值,页面输出 hello world    document.body.innerText = obj.text}
然后,修改 obj.text 的值。
obj.text = \\\'hello Vue\\\'
当我们修改了 obj.text 值的时候,希望把 effect() 自动执行一次,页面输出 hello Vue,这样的话 obj 这个对象就变成响应式数据,然后 effect 这个函数就自然成了「副作用函数」。
什么是响应式数据?
当 effect 执行的时候,会触发字段 obj.text「读取」操作,当修改 obj.text 值的时候,就会触发 obj.text「设置」操作,所以,我们需要拦截 obj 这个对象的「读取」和「设置」操作。
const obj = new Proxy(data,{    get(target, key){      //读取操作    },    set(target, key, newVal){      //设置操作    }})
在 Vue2 中,采用的是 Object.defineProperty 函数实现,在 Vue3 中,采用的是 Proxy 代理对象的方式。
实现一个简易的响应系统
    //存储副作用函数的桶const bucket = new Set()
    //原始数据const data = { text: \\\'hello world\\\'}
    //对原始数据做代理const obj = new Proxy(data, { //拦截读取操作 get(target, key) { //将副作用函数添加到桶中 bucket.add(effect) //返回属性值 return target[key] }, //拦截设置操作 set(target, key, newVal) { //设置属性值 target[key] = newVal //把副作用函数从桶里取出来执行 bucket.forEach(fn => fn()) //返回 true,表示代理成功 return true }})
    首先,我们创建一个 bucket(桶)来存储「副作用函数」,它是 Set 类型,有原始数据 data,再有原数据的代理对象 obj,我们分别设置 get 和 set 拦截函数,用来拦截「读取」和「设置」操作。
    当读取属性时,我们把副作用函数 effect 添加到 bucket 桶里,然后返回属性值,当设置属性时先更新原始数据,再将副作用函数从「桶」里取出来重新执行,这样就实现了响应式数据。
    使用代码来验证一下:
    //副作用函数function effect() {    document.body.innerText = obj.text}//执行副作用函数,触发读取effect()//1秒后修改响应数据setTimeout(() => {    obj.text = \\\'hello Vue3\\\'}, 1000)
    目前的代码是有一些缺陷的,因为我们直接通过 effect 来获取副作用函数,这属于硬编码,不灵活。我们应该去掉这种硬编码的方式,副作用函数名字可以随意取,可以换任意名字,也可以使用匿名函数。
    我们后续分享 …

    图片授权基于 www.pixabay.com 相关协议

    文章内容来源于《Vue.js 设计与实现》

    原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34573.html

    (0)
    小道研究's avatar小道研究
    上一篇 2024年4月10日 下午7:21
    下一篇 2024年4月10日 下午7:23

    相关推荐

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注