本篇內(nèi)容主要講解“vue3中effect與computed兩者之間的聯(lián)系”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“vue3中effect與computed兩者之間的聯(lián)系”吧!
目前創(chuàng)新互聯(lián)公司已為成百上千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、達(dá)孜網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶(hù)導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶(hù)和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。在我剛看完vue3響應(yīng)式的時(shí)候,心中就有一個(gè)不可磨滅的謎團(tuán),讓我茶不思飯不想,總想生病。那么這個(gè)謎團(tuán)是什么呢?就是在響應(yīng)式中一直穿行在tranger跟track之間的effect。如果單純的響應(yīng)式原理根本就用不上effect,那么effect到底是干什么的呢?
船到橋頭自然直,柳岸花明又一村??嘈娜颂觳回?fù),偶然間我看到了effect測(cè)試代碼用例!
it('should observe basic properties', () => { let dummy const counter = reactive({ num: 0 }) effect(() => (dummy = counter.num)) expect(dummy).toBe(0) counter.num = 7 expect(dummy).toBe(7) })
解釋一下,這段代碼
首先聲明dummy變量,然后在effect的回調(diào)中把已響應(yīng)的對(duì)象counter的num屬性賦值給dummy
然后做斷言判斷 dummy是否等于 0
將 counter.num 賦值 7 ,然后 dummy 也變成了 7 !
這,,,讓我想到了什么??
這就是computed的嗎?
趕緊看下 computed 的測(cè)試用例??!
const value = reactive<{ foo?: number }>({}) const cValue = computed(() => value.foo) expect(cValue.value).toBe(undefined) value.foo = 1 expect(cValue.value).toBe(1)
哈哈哈
阿哈哈哈哈
hhhhhhhhhhhhhhhhhhhh
忍不住想仰天長(zhǎng)嘯!!
果然跟我猜想的一樣?。?!我終于直到effect是個(gè)什么鬼了,顧名思義effect是副作用的意思,也就是說(shuō)它是響應(yīng)式副產(chǎn)品,每次觸發(fā)了 get 時(shí)收集effect,每次set時(shí)在觸發(fā)這些effects。這樣就可以做一些響應(yīng)式數(shù)據(jù)之外的一些事情了,比如計(jì)算屬性computed。
讓我們用effect實(shí)現(xiàn)一個(gè)computed 可能會(huì)更清晰一點(diǎn)
我就不寫(xiě)一些亂七八糟的判斷了,讓大家能夠看的更加清楚
function computed (fn) { let value = undefined const runner = effect(fn, { // 如果lazy不置為true的話(huà),每次創(chuàng)建effect的時(shí)候都會(huì)立即執(zhí)行一次 // 而我們要實(shí)現(xiàn)computed顯然是不需要的 lazy: true }) // 為什么要使用對(duì)象的形式,是因?yàn)槲覀冏詈笮枰玫絚omputed的值 // 如果不用對(duì)象的 get 方法的話(huà)我們就需要手動(dòng)再調(diào)用一次 computed() return { get value() { return runner() } } } // 使用起來(lái)是這樣的 const value = reactive({}) const cValue = computed(() => value.foo) value.foo = 1 console.log(cValue.value) // 1
這也太簡(jiǎn)單了吧,那么重點(diǎn)來(lái)了,effect怎么實(shí)現(xiàn)的呢?
別著急,我們先捋一下邏輯
首先 如果 effect 回調(diào)內(nèi)有已響應(yīng)的對(duì)象被觸發(fā)了 get 時(shí),effect就應(yīng)該被儲(chǔ)存起來(lái)
然后,我們需要一個(gè)儲(chǔ)存effect的地方,在effect函數(shù)調(diào)用的時(shí)候就應(yīng)該把effect放進(jìn)這個(gè)儲(chǔ)存空間,在vue中使用的是一個(gè)數(shù)組activeReactiveEffectStack = []
再后,每個(gè)target被觸發(fā)的時(shí)候,都可能有多個(gè)effect,所以每個(gè)target需要有一個(gè)對(duì)應(yīng)的依賴(lài)收集器 deps,等到 set 時(shí)遍歷 deps 執(zhí)行 effect()
然而,這個(gè)依賴(lài)收集器 deps 不能放在 target 本身上,這樣會(huì)使數(shù)據(jù)看起來(lái)不是很簡(jiǎn)潔,還會(huì)存在多余無(wú)用的數(shù)據(jù),所以我們需要一個(gè) map 集合來(lái)儲(chǔ)存 target 跟 deps 的關(guān)系, 在vue中這個(gè)儲(chǔ)存集合叫 targetMap 。
幾個(gè)概念
track 追蹤器,在 get 時(shí)調(diào)用該函數(shù),將所有 get 的 target 跟 key 以及 effect 建立起對(duì)應(yīng)關(guān)系
// 比如 const react = reactive({a: { b: 2 }) // react.a 時(shí) target -> {a: { b: 2 } key -> a // targetMap 儲(chǔ)存了 target --> Map --> key --> Set --> dep --> effect // 當(dāng)調(diào)用 react.a.b.c.d.e 時(shí) depsMap // {"a" => Set(1)} --> Set --> effect // {"b" => Set(1)} // {"c" => Set(1)} // {"d" => Set(1)} // {"e" => Set(1)} export function track(target: any, key: string) { const effect = activeReactiveEffectStack[activeReactiveEffectStack.length - 1]; if (effect) { let depsMap = targetMap.get(target); if (depsMap === void 0) { targetMap.set(target, (depsMap = new Map())); } let dep = depsMap.get(key!); if (!dep) { depsMap.set(key!, (dep = new Set())); } if (!dep.has(effect)) { dep.add(effect); effect.deps.push(dep); } } }
trigger 觸發(fā)器,這個(gè)就比較好理解了,拿到target key下的對(duì)應(yīng)的所有 effect,然后遍歷執(zhí)行 effect()
export function trigger(target: any, key?: string | symbol) { const depsMap: any = targetMap.get(target); const effects: any = new Set() if (depsMap && depsMap.get(key)) { depsMap.get(key).forEach((dep: any) => { effects.add(dep) }); effects.forEach((e: any) => e()) } }
effect 函數(shù)實(shí)現(xiàn)
// 暴露的 effect 函數(shù) export function effect( fn: Function, options: any = EMPTY_OBJ ): any { if ((fn as any).isEffect) { fn = (fn as any).raw } const effect = createReactiveEffect(fn, options) // 如果不是 lazy,則會(huì)立即執(zhí)行一次 if (!options.lazy) { effect() } return effect } // 創(chuàng)建 effect function createReactiveEffect( fn: Function, options: any ): any { const effect = function effect(...args: any): any { return run(effect as any, fn, args) } as any effect.isEffect = true effect.active = true effect.raw = fn effect.scheduler = options.scheduler effect.onTrack = options.onTrack effect.onTrigger = options.onTrigger effect.onStop = options.onStop effect.computed = options.computed effect.deps = [] return effect } // 執(zhí)行函數(shù),執(zhí)行完之后會(huì)將儲(chǔ)存的 effect 刪除 // 這是函數(shù) effect 的所有執(zhí)行,所經(jīng)歷的完整的聲明周期 function run(effect: any, fn: Function, args: any[]): any { if (!effect.active) { return fn(...args) } if (activeReactiveEffectStack.indexOf(effect) === -1) { try { activeReactiveEffectStack.push(effect) return fn(...args) } finally { activeReactiveEffectStack.pop() } } }
一口氣寫(xiě)了這么多,最后總結(jié)一下。在大家看源碼的時(shí)候,如果發(fā)現(xiàn)有哪個(gè)地方無(wú)從下手的話(huà),可以先從測(cè)試用例開(kāi)始看。因?yàn)闇y(cè)試用例可以很清楚的知道這個(gè)函數(shù)想要達(dá)到什么效果,然后從效果上想,為什么這么做,如果我自己寫(xiě)的話(huà)應(yīng)該怎么寫(xiě),這樣一點(diǎn)點(diǎn)就能揣摩出作者的意圖了。再根據(jù)源碼結(jié)合自己的想法你就能夠?qū)W到很多。
到此,相信大家對(duì)“vue3中effect與computed兩者之間的聯(lián)系”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。
本文名稱(chēng):vue3中effect與computed兩者之間的聯(lián)系-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://aaarwkj.com/article42/ddoihc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、用戶(hù)體驗(yàn)、微信公眾號(hào)、App開(kāi)發(fā)、動(dòng)態(tài)網(wǎng)站、軟件開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容