久久精品中文字幕免费_91香蕉国产亚洲一区二区三区_国产精品巨作无遮拦_亚洲人成电影

    <center id="oy65s"><ol id="oy65s"></ol></center>

  • <menu id="oy65s"></menu>
    當(dāng)前位置:首頁 > 足球資訊 > 正文內(nèi)容

    vue3 響應(yīng)式數(shù)據(jù)庫——reactive

    杏彩體育2年前 (2023-01-28)足球資訊54

    請仔細(xì)閱讀下面代碼,思考vue3是如何做響應(yīng)式數(shù)據(jù)的?

    let temp // reactive 是使對象變成一個代理 const counter = reactive({ num: 0 }); // effect主要職責(zé)是開啟依賴收集,等待get的調(diào)用完成正常的依賴存儲 effect(() => (temp = counter.num)); // 觸發(fā)更新 counter.num = 1; 復(fù)制代碼

    在這里是不是有的人要說,咋們在日常開發(fā)中,直接在 vue 模板上里面寫一個ref 自動幫我們進(jìn)行了開啟依賴收集,當(dāng)我們調(diào)用get的時候去存儲依賴。事出反常必有妖

    在vue源碼中的renderer.ts 中有這么這么個代碼片段

    const mountComponent: MountComponentFn = ( initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized ) => { // ...省略其他 // 這里會調(diào)用一個方法setupRenderEffect setupRenderEffect( instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized ) } const setupRenderEffect: SetupRenderEffectFn = ( instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized ) => { const componentUpdateFn = () => { // 省略組件更新邏輯 } // 這一段話的意思是創(chuàng)建一個 ReactiveEffect 來保存每一個獨立的proxy, // 和effect的效果是一樣的 const effect = new ReactiveEffect( componentUpdateFn, () => queueJob(instance.update), instance.scope // track it in components effect scope ) } 復(fù)制代碼

    總結(jié)下,咋們在模板中使用 ref,reactive等是vue本身在渲染的時候就會把整個組件放入ReactiveEffect中進(jìn)行依賴收集,對外拋出一個run方法,run方法用于決定是否需要進(jìn)行依賴收集哦,對于ref處理普通數(shù)據(jù)準(zhǔn)備另開篇幅

    reactive

    reactive 是用于把對象變成一個代理對象,proxy

    function createReactiveObject( target: Target, baseHandlers: ProxyHandler<any>, proxyMap: WeakMap<Target, any>) { // 核心就是 proxy // 目的是可以偵聽到用戶 get 或者 set 的動作 // 如果命中的話就直接返回就好了 // 使用緩存做的優(yōu)化點 const existingProxy = proxyMap.get(target); if (existingProxy) { return existingProxy; } const proxy = new Proxy(target, baseHandlers); // 把創(chuàng)建好的 proxy 給存起來, proxyMap.set(target, proxy); return proxy; } 復(fù)制代碼

    effect

    effect 函數(shù)的作用是用于開啟收集依賴,返回run函數(shù)

    export function effect<T = any>( fn: () => T, options?: ReactiveEffectOptions ): ReactiveEffectRunner { const _effect = new ReactiveEffect(fn); // 合并選項 extend(_effect, options); // 進(jìn)來時候就對開啟執(zhí)行run開啟依賴收集 _effect.run(); // 把 _effect.run 這個方法返回 // 讓用戶可以自行選擇調(diào)用的時機(調(diào)用 fn) const runner: any = _effect.run.bind(_effect); runner.effect = _effect; return runner; } // 在ReactiveEffect run函數(shù)的內(nèi)容是開啟允許依賴收集 export class ReactiveEffect { active = true; deps = []; public onStop?: () => void; constructor(public fn, public scheduler?) { console.log("創(chuàng)建 ReactiveEffect 對象"); } run() { // 運行 run 的時候,可以控制 要不要執(zhí)行后續(xù)收集依賴的一步 // 目前來看的話,只要執(zhí)行了 fn 那么就默認(rèn)執(zhí)行了收集依賴 // 這里就需要控制了 // 是不是收集依賴的變量 // 執(zhí)行 fn 但是不收集依賴 if (!this.active) { return this.fn(); } // 執(zhí)行 fn 收集依賴 // 可以開始收集依賴了 shouldTrack = true; // 執(zhí)行的時候給全局的 activeEffect 賦值 // 利用全局屬性來獲取當(dāng)前的 effect activeEffect = this as any; // 執(zhí)行用戶傳入的 fn const result = this.fn(); // 重置 shouldTrack = false; activeEffect = undefined; return result; } } 復(fù)制代碼

    baseHandlers

    baseHandlers 是用于處理proxy里面的get和set的,當(dāng)proxy調(diào)用get和set的時候就會去觸發(fā)對應(yīng)的函數(shù)

    get操作的流程如下:

    set 操作的流程如下:

    export const mutableHandlers: ProxyHandler<object> = { get:(isReadonly = false, shallow = false) { return function get(target, key, receiver) { // 獲取對target的key的值 const res = Reflect.get(target, key, receiver); // 問題:為什么是 readonly 的時候不做依賴收集呢 // readonly 的話,是不可以被 set 的, 那不可以被 set 就意味著不會觸發(fā) trigger // 所有就沒有收集依賴的必要了 if (!isReadonly) { // 在觸發(fā) get 的時候進(jìn)行依賴收集 track(target, "get", key); } // 把內(nèi)部所有的是 object 的值都用 reactive 包裹,變成響應(yīng)式對象 // 如果說這個 res 值是一個對象的話,那么我們需要把獲取到的 res 也轉(zhuǎn)換成 reactive if (isObject(res)) { // res 等于 target[key] return isReadonly ? readonly(res) : reactive(res); } return res; }; }, // set值的時候觸發(fā) set:(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); // 在觸發(fā) set 的時候進(jìn)行觸發(fā)依賴 trigger(target, "set", key); return result; };, }; 復(fù)制代碼

    track

    在get的時候,通知進(jìn)行依賴收集,

    在進(jìn)行依賴收集的時候,緩存?zhèn)魅氲膶ο螅?/p>

    這里在緩存依賴的步驟是:

    第一步: 當(dāng)運行counter.num 的時候會觸發(fā)proxy的get方法第二步: 全局有一個targetMap是一個weakMap 來記錄couter這個對象是否存在,并且weakMap的key是 couter這個對象,存在則使用,不存在則創(chuàng)建,counter的value又是一個Map,里面記錄著counter里面的key和counter對象的key是一一對應(yīng)的第三步: 在map中判斷key是 num的是否存在,存在則使用,不存在則創(chuàng)建一個Set來保存當(dāng)前的ReactiveEffect 對象,ReactiveEffect 對象含有run方法等待trigger觸發(fā)export function track(target, type, key) { if (!isTracking()) { return; } // 1. 先基于 target 找到對應(yīng)的 dep // 如果是第一次的話,那么就需要初始化 let depsMap = targetMap.get(target); if (!depsMap) { // 初始化 depsMap 的邏輯 depsMap = new Map(); targetMap.set(target, depsMap); } let dep = depsMap.get(key); if (!dep) { dep = createDep(); depsMap.set(key, dep); } if (!dep.has(activeEffect)) { dep.add(activeEffect); (activeEffect as any).deps.push(dep); } } 復(fù)制代碼

    trigger

    當(dāng)對于track來說,trigger需要做的事情就會簡單許多

    export function trigger(target, type, key) { const depsMap = targetMap.get(target); if (!depsMap) return; // 暫時只實現(xiàn)了 GET 類型 // get 類型只需要取出來就可以 const dep = depsMap.get(key); // 省略其他邏輯 // 觸發(fā)run函數(shù) for (const effect of dep) { if (effect.scheduler) { // scheduler 可以讓用戶自己選擇調(diào)用的時機 // 這樣就可以靈活的控制調(diào)用了 // 在 runtime-core 中,就是使用了 scheduler 實現(xiàn)了在 next ticker 中調(diào)用的邏輯 effect.scheduler(); } else { // 觸發(fā)函數(shù) effect.run(); } } } 復(fù)制代碼

    自己實現(xiàn)

    說了那么多,不如自己來實現(xiàn)一遍簡單的響應(yīng)式系統(tǒng)

    源碼地址

    掃描二維碼推送至手機訪問。

    版權(quán)聲明:本文由財神資訊-領(lǐng)先的體育資訊互動媒體轉(zhuǎn)載發(fā)布,如需刪除請聯(lián)系。

    本文鏈接:http://www.daniuzhishi.com/?id=44547

    “vue3 響應(yīng)式數(shù)據(jù)庫——reactive” 的相關(guān)文章

    【競彩足球競猜】英格蘭vs伊朗 世界杯

    【競彩足球競猜】英格蘭vs伊朗 世界杯

    【競彩足球競猜】英格蘭vs伊朗 【競彩足球競猜】英格蘭vs伊朗 【競彩足球競猜】 英格蘭vs伊朗 2022年11月20日 00:00 英格蘭 英格蘭男子足球代表隊在整個世界足壇都是實力雄厚的球隊,這支球隊除了1994年、1...

    韓職聯(lián)今日開賽,競彩足球全面開售各玩法

    由于各大主流足球聯(lián)賽受疫情影響紛紛延期或停擺,競彩足球自3月25日起暫停發(fā)布。今日,韓國職業(yè)聯(lián)賽正式開賽,競彩也已同步開售相關(guān)賽事,廣大購彩者又能體驗到足球賽事和競猜游戲的雙重歡樂了。...

    中國足彩網(wǎng)競彩27日推薦:看好德國阻擊西班牙

    中國足彩網(wǎng)競彩27日推薦:看好德國阻擊西班牙

      世界杯 西班牙VS德國   比賽時間:2022-11-28   03:00   球場:海灣球場   西班牙男足在去年歐洲杯晉級四強,已經(jīng)宣告實力回歸,佩德里,加維等小將實力崛起。本次世界杯,西班牙也是奪冠熱門之一,球隊低調(diào)出行,值...

    國際足球場與普通足球場的區(qū)別及標(biāo)準(zhǔn)尺寸規(guī)格!

    國際足球場與普通足球場的區(qū)別及標(biāo)準(zhǔn)尺寸規(guī)格!

      足球場整體是矩形的。長的兩邊是稱為邊線。另外兩邊側(cè)面被稱為球門線。兩個球門線必須50至100碼,并具有相同的長度。兩個邊線也必須具有相同的長度,以及在100至130碼的長度之間。所有線條必須是等寬的,不超過12厘米。   國際足球場的標(biāo)準(zhǔn)規(guī)格尺寸是由國際足協(xié)制定。對于...

    98 年世界杯在足球史上的影響有哪些?

    沒有舉足輕重的作用。 對足球發(fā)展有著轉(zhuǎn)折性意義,且前無古人后未見來者的年份,是1970年世界杯。 原因如下: 1、全球轉(zhuǎn)播 2、彩色電視轉(zhuǎn)播 3...

    2019年國際大體聯(lián)足球世界杯開賽

    2019年國際大體聯(lián)足球世界杯開賽

    墨西哥國立自治大學(xué)隊2號球員帕洛馬雷斯用一記頭球打破僵局。新華網(wǎng)發(fā)(林楷煜 攝)新華網(wǎng)福州11月22日電(王雄)11月21日晚,卡爾美2019年國際大體聯(lián)足球世界杯在福建晉江足球公園開賽。在當(dāng)晚舉行的一場焦點比賽上,東道主球隊北京理工大學(xué)以0比1...

    ?