最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3 源碼解讀之 time slicing的使用方法

 更新時(shí)間:2019年10月31日 11:13:59   作者:132  
這篇文章主要介紹了vue3 源碼解讀之 time slicing的使用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

今天給大家?guī)?lái)一篇源碼解析的文章,emm 是關(guān)于 vue3 的,vue3 源碼放出后,已經(jīng)有很多文章來(lái)分析它的源碼,我覺(jué)得很快又要爛大街了,哈哈

不過(guò)今天我要解析的部分是已經(jīng)被廢除的 time slicing 部分,這部分源碼曾經(jīng)出現(xiàn)在 vue conf 2018 的視頻中,但是源碼已經(jīng)被移除掉了,之后可能也不會(huì)有人關(guān)注,所以應(yīng)該不會(huì)爛大街

打包

閱讀源碼之前,需要先進(jìn)行打包,打包出一份干凈可調(diào)試的文件很重要

vue3 使用的 rollup 進(jìn)行打包,我們需要先對(duì)它進(jìn)行改造

import cleanup from 'rollup-plugin-cleanup'
plugins: [
  cleanup() //增加了一個(gè) cleanup 插件
   
  tsPlugin,
  aliasPlugin,
  createReplacePlugin(isProductionBuild, isBunlderESMBuild, isCompat),
  ...plugins
],

增加 cleanup 插件主要目的是打包出無(wú)注釋的文件

以上,是我個(gè)人閱讀源碼的習(xí)慣,我覺(jué)得注釋和類型的作用就是礙眼的,所以先去掉再說(shuō)

用例

我們?cè)谧x源碼之前,需要先實(shí)現(xiàn)一個(gè)正確用例,但是我讀的這個(gè)版本的源碼,還是 class 的,怎么辦?

這個(gè)時(shí)候我們可以根據(jù)測(cè)試用例來(lái)猜測(cè)并給出代碼

function block () {
 const start = performance.now()
 while (performance.now() - start < 2) {
 }
}

class Test extend Component {
 render (props) {
  block()
  return h('li', props.msg)
 }
}

class App extend Component {
 msg = ''
 render () {
  const list = []
  for (let i = 0; i < 200; i++) {
   list.push(h(Test, { key: i, msg: this.msg }))
  }
  return [
   h('input', {
    onInput: e => {
     this.msg = e.target.value
    }
   }),
   h('div',list)
  ]
 }
}

很好,現(xiàn)在我們有了一個(gè)爭(zhēng)取,簡(jiǎn)單的用例了,接下來(lái)就是一股腦調(diào)試

調(diào)試

由于我在 fre 中也實(shí)現(xiàn)了時(shí)間切片,所以我對(duì)它非常了解,我知道它的作用原理,所以我們直接搜索宏任務(wù),哈,果然有

window.addEventListener('message', event => {
  if (event.source !== window || event.data !== key) {
    return;
  }
  flushStartTimestamp = getNow();
  try {
    flush();
  }
  catch (e) {
    handleError(e);
  }
}, false);
function flushAfterMacroTask() {
  window.postMessage(key, `*`);
}

這段代碼非常容易理解,就是在宏任務(wù)隊(duì)列里執(zhí)行了 flush 函數(shù),繼續(xù)

然后關(guān)鍵就來(lái)了

function flush() {
  let job;
  while (true) {
    job = stageQueue.shift();
    if (job) {
      stageJob(job);
    }
    else {
      break;
    }
    {
      const now = getNow();
      if (now - flushStartTimestamp > frameBudget && job.expiration > now) {
        break; // 此處為關(guān)鍵,意思是超過(guò)16ms,或者任務(wù)過(guò)期,跳出循環(huán)
      }
    }
  }
  ... 以下代碼省略...

上面的循環(huán)很關(guān)鍵,它做的事情很簡(jiǎn)單的,從 stageQueue 里出棧一個(gè)任務(wù),然后執(zhí)行 stateJob

stateJob 做的事情很簡(jiǎn)單,就是往 commitQueue 里 push 這個(gè)任務(wù)

function stageJob(job) {
  if (job.ops.length === 0) {
    currentJob = job;
    job.cleanup = job();
    currentJob = null;
    commitQueue.push(job); //重點(diǎn)在這里
    job.status = 2;
  }
}

到目前為止,我們?cè)创a讀了一丟丟,但是已經(jīng)幾乎讀完了可以說(shuō)

它的本質(zhì)就是,在宏任務(wù)中,stageQueue 作為低優(yōu)先級(jí)任務(wù)隊(duì)列,不斷的出棧,然后分批次(16ms 的閾值)入棧到 commitQueue 里

呼,其實(shí)如果不是寫文章,就可以到此為止了,但是寫文章為了湊字?jǐn)?shù)嘛,我們繼續(xù)

上面我們已經(jīng)知道了兩個(gè)隊(duì)列,stageQueue 和 commitQueue,但是并不知道他們里面都是什么東西

是什么東西被調(diào)度的呢?打印一下,你就知道:

console.log(stageQueue,commitQueue)

得出的結(jié)果是

function mountComponentInstance(){...}

看名字就知道是組件掛載函數(shù),當(dāng)然組件更新和卸載的函數(shù)也是同理

到現(xiàn)在,我們也知道了參與調(diào)度的是組件掛載更新的函數(shù),所以本質(zhì)上,vue 的時(shí)間切片的基本單位是組件,也就是說(shuō),如果你的組件掛載需要一個(gè)小時(shí),那你仍然要卡一小時(shí)

湊字?jǐn)?shù)

剩下的內(nèi)容純屬湊字?jǐn)?shù),就是除了核心調(diào)度之外的東西

比如 commitQueue 是操作 dom 的,那它咋個(gè)操作

function commitJob(job) {
  const { ops, postEffects } = job;
  for (let i = 0; i < ops.length; i++) {
    applyOp(ops[i]); // 重點(diǎn)在這里
  }
  if (postEffects) {
    postEffectsQueue.push(...postEffects);
  }
  resetJob(job);
  job.status = 0;
}

如上,拿到 ops,然后進(jìn)行操作,我們看一下 ops 是啥就行了

[<div></div>, <li></li>, function CreactElement(){}]

湊合湊合,是個(gè)數(shù)組,包含了 dom 操作的方法和被操作的元素

然后這個(gè)過(guò)程是同步完成的,也就是所謂的高優(yōu)先級(jí)任務(wù),必須等到徹底收集完畢,才可以循環(huán)執(zhí)行它

做完這個(gè),postEffectQueue 主要是一些額外的副作用和清理工作,我實(shí)在湊字?jǐn)?shù)無(wú)能,就不打印了

總結(jié)

最后我們用最直白的話,總結(jié)一下:

在宏任務(wù)隊(duì)列中,不斷的從 stageQueue 分批次(16ms)將組件的函數(shù)轉(zhuǎn)移到 commitQueue 里,轉(zhuǎn)移完了,同步操作 dom

原理其實(shí)還是利用了宏任務(wù)隊(duì)列,其實(shí)現(xiàn)在 vue 的做法和 fre 也有一點(diǎn)點(diǎn)類似,fre 是在宏任務(wù)中,盡可能更多的去訪問(wèn) reconcile 大循環(huán)

關(guān)于廢除

如開頭提到的,time slicing 這部分內(nèi)容已經(jīng)在 master 分支被移除了,關(guān)于為什么廢除,我特地發(fā)了 issue,可以戳這里:(天啊,我和尤終于可以和平地進(jìn)行交談了)

https://github.com/vuejs/rfcs/issues/89

簡(jiǎn)單說(shuō),就是 time slicing 的收益不大,除了 issue 中提到的,它本身的場(chǎng)景就少的可憐

也因?yàn)?vue 現(xiàn)在的實(shí)現(xiàn),由于調(diào)度的基本單位是組件,所以它仍然會(huì)因?yàn)榻M件內(nèi)部的邏輯而被阻斷

比如我把用例中用于阻斷的 block 函數(shù)改為 1s,就已經(jīng)徹底卡死了

思考

從 issue 和源碼本身,我們可以思考一些問(wèn)題,同時(shí)用來(lái)湊字?jǐn)?shù)

時(shí)間切片是否必須?

答案是否定的,尤的回復(fù)已經(jīng)足夠充分了:https://github.com/vuejs/rfcs/issues/89#issuecomment-546988615

大致有兩點(diǎn):

  • 除了高幀率動(dòng)畫,其他的場(chǎng)景幾乎都可以使用防抖和節(jié)流去提高響應(yīng)性能
  • vue 現(xiàn)在的實(shí)現(xiàn),粒度太大,最終的效果十分有限,不值得

那,fre 呢?

fre 的異步渲染,是否也存在這個(gè)問(wèn)題,不得不承認(rèn),fre 雖然粒度很小,對(duì)于組件內(nèi)部的阻斷可以搞定,但是元素本身也可以被阻斷

而且第一個(gè)問(wèn)題也是存在的,就是沒(méi)有太多適用場(chǎng)景

但是 fre 源碼層面還是意義重大的,即便這玩意搞出來(lái),發(fā)現(xiàn)它作用不大,副作用不小,但 fre 作為我個(gè)人的學(xué)習(xí)和研究的項(xiàng)目,它的價(jià)值從來(lái)就不是業(yè)務(wù)層面的

只是我應(yīng)該停下來(lái),異步渲染搞定了,只是向大家展示它的源碼實(shí)現(xiàn),未來(lái)不應(yīng)該跟隨 react 去搞一堆業(yè)務(wù) API,如 useTransition 等等

關(guān)于源碼?

vue3 發(fā)版當(dāng)天,源碼解讀就放出了,但是到目前為止,所有的源碼解讀統(tǒng)統(tǒng)都是蹭熱度的
不久的將來(lái),vue 的源碼又要爛大街了……
這種現(xiàn)象引起反省,我們讀源碼到底是為了什么?為了面試嗎?為了更好的寫業(yè)務(wù)?
對(duì)我而言,僅僅只是感興趣,我對(duì)這部分源碼感興趣,我就去讀,并且只讀感興趣的部分
其實(shí)大家也看到了,我很少寫源碼解讀的文章,因?yàn)槲乙恢狈磳?duì)所謂的【通讀源碼】
將閱讀源碼作為一項(xiàng)工作,同樣的小函數(shù),讀了一遍又一遍,重復(fù)勞動(dòng)
這和糊 shi 有什么區(qū)別呢?

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue封裝全局過(guò)濾器Filters的步驟

    Vue封裝全局過(guò)濾器Filters的步驟

    這篇文章主要介紹了Vue封裝全局過(guò)濾器Filters的步驟,通過(guò)封裝vue全局過(guò)濾器實(shí)現(xiàn)filters的統(tǒng)一管理。感興趣的朋友可以了解下
    2020-09-09
  • Object.assign觸發(fā)watch原理示例解析

    Object.assign觸發(fā)watch原理示例解析

    這篇文章主要為大家介紹了Object.assign觸發(fā)watch原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Vue中父子組件的值傳遞與方法傳遞

    Vue中父子組件的值傳遞與方法傳遞

    這篇文章主要介紹了Vue中父子組件的值傳遞與方法傳遞,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 詳解vue 兼容IE報(bào)錯(cuò)解決方案

    詳解vue 兼容IE報(bào)錯(cuò)解決方案

    這篇文章主要介紹了詳解vue 兼容IE報(bào)錯(cuò)解決方案,詳細(xì)的介紹了幾種原因及其解決方案,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-12-12
  • vue3+vite 動(dòng)態(tài)引用靜態(tài)資源及動(dòng)態(tài)引入assets文件夾圖片的多種方式

    vue3+vite 動(dòng)態(tài)引用靜態(tài)資源及動(dòng)態(tài)引入assets文件夾圖片的多種方式

    通過(guò)require動(dòng)態(tài)引入, 發(fā)現(xiàn)報(bào)錯(cuò):require is not defind,這是因?yàn)?nbsp;require 是屬于 Webpack 的方法,本文給大家介紹vue3+vite 動(dòng)態(tài)引用靜態(tài)資源及動(dòng)態(tài)引入assets文件夾圖片的多種方式,感興趣的朋友一起看看吧
    2023-10-10
  • Vant2移動(dòng)端Vue組件庫(kù)問(wèn)題記錄

    Vant2移動(dòng)端Vue組件庫(kù)問(wèn)題記錄

    Vant是一套輕量、可靠的移動(dòng)端組件庫(kù),通過(guò)Vant可以快速搭建出風(fēng)格統(tǒng)一的頁(yè)面,提升開發(fā)效率,下面這篇文章主要給大家介紹了關(guān)于Vant2移動(dòng)端Vue組件庫(kù)問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色)

    Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色)

    很多應(yīng)用都會(huì)需要對(duì)不同的用戶進(jìn)行權(quán)限控制,本文主要介紹了Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無(wú)法輸入的問(wèn)題

    vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無(wú)法輸入的問(wèn)題

    這篇文章主要介紹了vue在使用element組件出現(xiàn)<el-input>標(biāo)簽無(wú)法輸入的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 深入理解vuex2.0 之 modules

    深入理解vuex2.0 之 modules

    本篇文章主要介紹了vuex2.0 之 modules,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • vuejs使用axios異步訪問(wèn)時(shí)用get和post的實(shí)例講解

    vuejs使用axios異步訪問(wèn)時(shí)用get和post的實(shí)例講解

    今天小編就為大家分享一篇vuejs使用axios異步訪問(wèn)時(shí)用get和post的實(shí)例講解,具有很好的參考價(jià)值。希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08

最新評(píng)論

城口县| 麻城市| 丽水市| 兴宁市| 会昌县| 日喀则市| 哈密市| 丰县| 西乡县| 吴江市| 凤庆县| 长春市| 望城县| 凤翔县| 孝义市| 潢川县| 鹤庆县| 东城区| 隆化县| 木兰县| 溧水县| 芜湖市| 博湖县| 翁牛特旗| 大洼县| 丹阳市| 镇江市| 定结县| 梁山县| 象山县| 南川市| 通许县| 邹平县| 石家庄市| 中西区| 盖州市| 林州市| 巴林左旗| 五指山市| 辉县市| 东兰县|