成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

解析Vue編譯器optimize源碼

3403771864 / 389人閱讀

  之前我們講過template轉(zhuǎn)成AST(抽象語法樹),現(xiàn)在我就繼續(xù)對模型樹優(yōu)化,進行靜態(tài)標注。這要如何實現(xiàn)?

  在源碼的注釋中我們找到了下面這段話:

  /** * Goal of the optimizer: walk the generated template AST tree * and detect sub-trees that are purely static, i.e. parts of * the DOM that never needs to change. * * Once we detect these sub-trees, we can: * * 1. Hoist them into constants, so that we no longer need to * create fresh nodes for them on each re-render; * 2. Completely skip them in the patching process. */

  永遠不需要變化的DOM就是靜態(tài)的。

  重新渲染時,作為常量,無需創(chuàng)建新節(jié)點;

  optimize 源碼之旅

  function optimize(root, options) { if (!root) { return } isStaticKey = genStaticKeysCached(options.staticKeys || ''); isPlatformReservedTag = options.isReservedTag || no; // first pass: mark all non-static nodes. markStatic$1(root); // second pass: mark static roots. markStaticRoots(root, false); }

  現(xiàn)在我們看到源碼并不復雜初始定義了兩個變量。

  isStaticKey 獲取 genStaticKeysCached函數(shù)返回值, 獲取makeMap(點此查看) 函數(shù)返回值引用 。

  isPlatformReservedTag 獲取編譯器選項isReservedTag的引用,檢查給定的字符是否是保留的標簽。

  接下來就是兩個重要的方法 markStatic$1 標注靜態(tài)節(jié)點、markStaticRoots 標注靜態(tài)根節(jié)點,我們先來看下 markStatic$1的源碼。

  markStatic$1源碼

  function markStatic$1(node) { node.static = isStatic(node); if (node.type === 1) { // do not make component slot content static. this avoids // 1. components not able to mutate slot nodes // 2. static slot content fails for hot-reloading if ( !isPlatformReservedTag(node.tag) && node.tag !== 'slot' && node.attrsMap['inline-template'] == null ) { return } for (var i = 0, l = node.children.length; i < l; i++) { var child = node.children[i]; markStatic$1(child); if (!child.static) { node.static = false; } } if (node.ifConditions) { for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) { var block = node.ifConditions[i$1].block; markStatic$1(block); if (!block.static) { node.static = false; } } } } }

  第一步我們要對節(jié)點做出判斷并標注。

  node.static = isStatic(node);

  在這給元素描述對象(AST) 擴展了static屬性,通過isStatic方法調(diào)用后返回值,這樣就可以區(qū)分出靜態(tài)和動態(tài)。

  isStatic源碼

  function isStatic(node) { if (node.type === 2) { // expression return false } if (node.type === 3) { // text return true } return !!(node.pre || ( !node.hasBindings && // no dynamic bindings !node.if && !node.for && // not v-if or v-for or v-else !isBuiltInTag(node.tag) && // not a built-in isPlatformReservedTag(node.tag) && // not a component !isDirectChildOfTemplateFor(node) && Object.keys(node).every(isStaticKey) )) }

  判斷node.type的值為2,那返回的就是false,node.type的值為3,表示為靜態(tài)文本返回 true 總結(jié):節(jié)點類型為表達式,標注為非靜態(tài);普通文本為靜態(tài)。

  上面的很容易理解

  復雜點的

  return !!(node.pre || ( !node.hasBindings && // no dynamic bindings !node.if && !node.for && // not v-if or v-for or v-else !isBuiltInTag(node.tag) && // not a built-in isPlatformReservedTag(node.tag) && // not a component !isDirectChildOfTemplateFor(node) && Object.keys(node).every(isStaticKey) ))

  節(jié)點類型為表達式,標注為非靜態(tài);普通文本為靜態(tài)。

  無動態(tài)綁定

  沒有 v-if 和 v-for 指令

  不是內(nèi)置的標簽

  是平臺保留標簽(html和svg標簽)

  不是 template 標簽的直接子元素并且沒有包含在 for 循環(huán)中

  結(jié)點包含的屬性只能有isStaticKey中指定的幾個

  現(xiàn)在你知道了 node.static=isStatic(node) 什么情況為false, 什么情況為true吧!

  回歸到markStatic$1

  if (node.type === 1) { // do not make component slot content static. this avoids // 1. components not able to mutate slot nodes // 2. static slot content fails for hot-reloading if ( !isPlatformReservedTag(node.tag) && node.tag !== 'slot' && node.attrsMap['inline-template'] == null ) { return } for (var i = 0, l = node.children.length; i < l; i++) { var child = node.children[i]; markStatic$1(child); if (!child.static) { node.static = false; } } if (node.ifConditions) { for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 < l$1; i$1++) { var block = node.ifConditions[i$1].block; markStatic$1(block); if (!block.static) { node.static = false; } } } }

  來看看它做了什么,通過一個 if 判斷node.type值為1,對標簽節(jié)點進行處理。如果遇到特殊情況會直接退出去。 什么特殊情況呢?

  // do not make component slot content static. this avoids // 1. components not able to mutate slot nodes // 2. static slot content fails for hot-reloading if ( !isPlatformReservedTag(node.tag) && node.tag !== 'slot' && node.attrsMap['inline-template'] == null ) { return }

  當遇到了非平臺保留標簽 isPlatformReservedTag(node.tag), 并且標簽節(jié)點是 slot,并且節(jié)點中有inline-template(內(nèi)聯(lián)模板)三者都滿足此時會終止函數(shù)的執(zhí)行。

  如果不滿足條件:

  for (var i = 0, l = node.children.length; i &lt; l; i++) { var child = node.children[i]; markStatic$1(child); if (!child.static) { node.static = false; } }

  通過 node.children 找到子節(jié)點,遞歸子節(jié)點。

  if (!child.static) { node.static = false; }

  當子節(jié)點非靜態(tài),那么該節(jié)點也標注非靜態(tài) 。其實這就里面還需要優(yōu)化,在之后的Vue3.0中增加了"動靜分離的策略" 尤大稱之為 Block tree 可以繼續(xù)與大家溝通。

  接下來看下 markStaticRoots。

  markStaticRoots 源碼

  function markStaticRoots(node, isInFor) { if (node.type === 1) { if (node.static || node.once) { node.staticInFor = isInFor; } //一個節(jié)點要成為根節(jié)點,那么要滿足以下條件: //1、靜態(tài)節(jié)點,并且有子節(jié)點 //2、子節(jié)點不能僅為一個文本節(jié)點 if (node.static &amp;&amp; node.children.length &amp;&amp; !( node.children.length === 1 &amp;&amp; node.children[0].type === 3 )) { node.staticRoot = true; return } else { node.staticRoot = false; } //循環(huán)遞歸標記 if (node.children) { for (var i = 0, l = node.children.length; i &lt; l; i++) { markStaticRoots(node.children[i], isInFor || !!node.for); } } if (node.ifConditions) { for (var i$1 = 1, l$1 = node.ifConditions.length; i$1 &lt; l$1; i$1++) { markStaticRoots(node.ifConditions[i$1].block, isInFor); } } } }

  一個節(jié)點要成為靜態(tài)根節(jié)點,需要滿足以下條件:

  自身為靜態(tài)節(jié)點,并且有子節(jié)點

  子節(jié)點不能僅為一個文本節(jié)點

  要是到第二個條件,這樣就會讓標記靜態(tài)根節(jié)點的受益較小。可以以此遞歸循環(huán)其子節(jié)點,循環(huán)標記。


文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/127975.html

相關(guān)文章

  • JS每日一題:簡述一下Vue.js的template編譯過程?

    摘要:問簡述一下的編譯過程先上一張圖大致看一下整個流程從上圖中我們可以看到是從后開始進行中整體邏輯分為三個部分解析器將模板字符串轉(zhuǎn)換成優(yōu)化器對進行靜態(tài)節(jié)點標記,主要用來做虛擬的渲染優(yōu)化代碼生成器使用生成函數(shù)代碼字符串開始前先解釋一下抽象 20190215問 簡述一下Vue.js的template編譯過程? 先上一張圖大致看一下整個流程showImg(https://image-static....

    NicolasHe 評論0 收藏0
  • Vue譯器AST抽象語法樹源碼分析

     直接進入核心現(xiàn)在說說baseCompile核心代碼:  //`createCompilerCreator`allowscreatingcompilersthatusealternative   //parser/optimizer/codegen,e.gtheSSRoptimizingcompiler.   //Herewejustexportadefaultcompilerusingthede...

    3403771864 評論0 收藏0
  • Vue原理】Compile - 源碼版 之 optimize 標記靜態(tài)節(jié)點

    摘要:一旦我們檢測到這些子樹,我們可以把它們變成常數(shù),這樣我們就不需要了在每次重新渲染時為它們創(chuàng)建新的節(jié)點在修補過程中完全跳過它們。否則,吊裝費用將會增加好處大于好處,最好總是保持新鮮。 寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,...

    Soarkey 評論0 收藏0
  • Vue原理】Compile - 源碼版 之 從新建實例到 compile結(jié)束的主要流程

    摘要:頁面這個實例,按理就需要解析兩次,但是有緩存之后就不會理清思路也就是說,其實內(nèi)核就是不過是經(jīng)過了兩波包裝的第一波包裝在中的內(nèi)部函數(shù)中內(nèi)部函數(shù)的作用是合并公共和自定義,但是相關(guān)代碼已經(jīng)省略,另一個就是執(zhí)行第二波包裝在中,目的是進行緩存 寫文章不容易,點個贊唄兄弟 專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 ...

    CODING 評論0 收藏0
  • vue原理Compile之optimize標記靜態(tài)節(jié)點源碼示例

      引言  optimize的內(nèi)容雖然不多,但十分重要,它是一個更新性能優(yōu)化,現(xiàn)在來說說:  首先找到optimize位置,就在 parse 處理完之后,generate 之前  varast=parse(template.trim(),options);   if(options.optimize!==false){   optimize(ast,options);   }   varcode=...

    3403771864 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<