<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                >PS:個人筆記,僅供參考,需要深入了解請閱讀參考資料。 # 參考資料 [https://ustbhuangyi.github.io/vue-analysis/prepare/directory.html#sfc](https://ustbhuangyi.github.io/vue-analysis/prepare/directory.html#sfc) # 編譯入口 ```js export const createCompiler = createCompilerCreator(function baseCompile ( template: string, options: CompilerOptions ): CompiledResult { const ast = parse(template.trim(), options) optimize(ast, options) const code = generate(ast, options) return { ast, render: code.render, staticRenderFns: code.staticRenderFns } }) ``` Vue.js 在不同的平臺下都會有編譯的過程,因此編譯過程中的依賴的配置`baseOptions`會有所不同。 找到編譯入口后,它主要執行了以下邏輯: - 解析模板字符串生成 AST ```js const ast = parse(template.trim(), options) ``` - 優化語法樹 ```js optimize(ast, options) ``` - 生成代碼 ```js const code = generate(ast, options) ``` # parse 編譯過程首先就是對模板做解析,生成 AST,它是一種抽象語法樹,是對源代碼的抽象語法結構的樹狀表現形式。在很多編譯技術中,如 babel 編譯 ES6 的代碼都會先生成 AST。 ```html <ul :class="bindCls" class="list" v-if="isShow"> <li v-for="(item,index) in data" @click="clickItem(index)">{{item}}:{{index}}</li> </ul> ``` 經過`parse`過程后,生成的 AST 如下: ```js ast = { 'type': 1, 'tag': 'ul', 'attrsList': [], 'attrsMap': { ':class': 'bindCls', 'class': 'list', 'v-if': 'isShow' }, 'if': 'isShow', 'ifConditions': [{ 'exp': 'isShow', 'block': // ul ast element }], 'parent': undefined, 'plain': false, 'staticClass': 'list', 'classBinding': 'bindCls', 'children': [{ 'type': 1, 'tag': 'li', 'attrsList': [{ 'name': '@click', 'value': 'clickItem(index)' }], 'attrsMap': { '@click': 'clickItem(index)', 'v-for': '(item,index) in data' }, 'parent': // ul ast element 'plain': false, 'events': { 'click': { 'value': 'clickItem(index)' } }, 'hasBindings': true, 'for': 'data', 'alias': 'item', 'iterator1': 'index', 'children': [ 'type': 2, 'expression': '_s(item)+":"+_s(index)' 'text': '{{item}}:{{index}}', 'tokens': [ {'@binding':'item'}, ':', {'@binding':'index'} ] ] }] } ``` 可以看到,生成的 AST 是一個樹狀結構,每一個節點都是一個`ast element`,除了它自身的一些屬性,還維護了它的父子關系,如`parent`指向它的父節點,`children`指向它的所有子節點。 # optimize 當我們的模板`template`經過`parse`過程后,會輸出生成 AST 樹,那么接下來我們需要對這顆樹做優化,為什么要有優化過程,因為我們知道 Vue 是數據驅動,是響應式的,但是我們的模板并不是所有數據都是響應式的,也有很多數據是首次渲染后就永遠不會變化的,那么這部分數據生成的 DOM 也不會變化,我們可以在`patch`的過程跳過對他們的比對。 `optimize`的過程,就是深度遍歷這個 AST 樹,去檢測它的每一顆子樹是不是靜態節點,如果是靜態節點則它們生成 DOM 永遠不需要改變,`optimize`把整個 AST 樹中的每一個 AST 元素節點標記了`static`和`staticRoot`,它會影響接下來執行代碼生成的過程。 ```js function isStatic (node: ASTNode): boolean { 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) )) } ``` # codegen ```html <ul :class="bindCls" class="list" v-if="isShow"> <li v-for="(item,index) in data" @click="clickItem(index)">{{item}}:{{index}}</li> </ul> ``` 上面這段代碼經過編譯,執行`const code = generate(ast, options)`,生成的`render`代碼串如下: ```js with(this){ return (isShow) ? _c('ul', { staticClass: "list", class: bindCls }, _l((data), function(item, index) { return _c('li', { on: { "click": function($event) { clickItem(index) } } }, [_v(_s(item) + ":" + _s(index))]) }) ) : _e() } ``` 這里的`_c`函數定義在`src/core/instance/render.js`中。 ```js vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false) ``` 而`_l`、`_v`定義在`src/core/instance/render-helpers/index.js`中: ```js export function installRenderHelpers (target: any) { target._o = markOnce target._n = toNumber target._s = toString target._l = renderList target._t = renderSlot target._q = looseEqual target._i = looseIndexOf target._m = renderStatic target._f = resolveFilter target._k = checkKeyCodes target._b = bindObjectProps target._v = createTextVNode target._e = createEmptyVNode target._u = resolveScopedSlots target._g = bindObjectListeners } ``` 顧名思義,`_c`就是執行`createElement`去創建 VNode,而`_l`對應`renderList`渲染列表;`_v`對應`createTextVNode`創建文本 VNode;`_e`對于`createEmptyVNode`創建空的 VNode。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看