精读《Vuejs设计与实现》days22

103 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情

4.8 计算属性computed 与 lazy

先讲一下lazy吧,lazy与调度器一样,是effect的一个属性,目的就是阻止effect的自动执行。

在vue的watch中有一个属性immediate,控制回调监听是否立即执行一次,lazy也是这个意思。

effect(()=>{},{lazy:true})

于是我们要继续修改effect的代码,新增lazy这个选项,并默认为false,也就是说。这里要注意一下,runEffect这个函数也需要修改一下,因为它本身没有return,会返回undefined

const effect = ((fn,options={lazy:false})=>{ 
    const runEffect=()=>{ 
        cleanup(runEffect) // 清除重复依赖 
        activeEffect = runEffect 
        effectStack.unshift(runEffect) //将副作用函数压入栈中 
        const result = fn() //新增,接收fn返回值
        effectStack.pop() // 执行完成后,出栈 
        activeEffect = effectStack.at(-1) //将activeEffect对准栈底 
        return result
    } 
    runEffect.deps=[] 
    runEffect.options = options //将options挂到对应的副作用函数上
    if(!options.lazy){ // 新增
     runEffect() 
    }
    return runEffect
})

原理其实很简单,就是判断一下lazy这个选项,如果不存在就先执行一次,最后把咱们封装好的副作用函数返回出去。 看一下我们上一篇文章的例子

const data = reactive({num:0})
const _effect = effect(
    ()=>{console.log(data.num)},
    {lazy:true}
)
data.num++
data.num++
_effect() //手动执行副作用函数

这样其实就是手动执行副作用,相当于我们留下了一个接口,保证能在手动优化代码。其实在vueuse这个库中,就大量使用了这种方法.

const { execute } = useFetch(url, { immediate: false })

我通常把这种操作叫做手动化。有的时候,我需要向外提供手动化的接口,这样可以提供更高的灵活性.大部分时候,我们需要程序一直往下执行,直到得到想要的结果。但是有的时候手动化可以提供更高的灵活性。所谓灵活性就是就是适应更多情况的程度。

比如@vueuse/core中的useFetch,一般情况,我们可能是这样.省略了模板中的一个按钮

<script setup>
const handleClick = async ()=>{
    await useFetch(url)
}
</script>

这样其实没什么问题,但是每次点击按钮才会去初始化,其实并不够灵活,我们通过手动执行,可以做到提前初始化fetch,点击的时候再执行

<script setup>
const { execute } = useFetch(url, { immediate: false })
const handleClick = async ()=>{
    await execute()
}
</script>

如果,你这个按钮要使用10次,或者添加其他别的操作,这样做显然更加灵活。

下一篇,我们讲一下computed的实现