<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                >[success] # patch 方法分析(二) ~~~ 1.上一個章節分析后,patch更新主要分為兩塊,一塊是新老虛擬dom相同,一塊是不同,這里是對 不同位置的分析 ~~~ >[info] ## 分析patch 里面createElm ~~~ 注意:這一步只是將虛擬dom 的結構創建為真實dom保存在虛擬dom屬性的'elm'中,此時并沒有 將虛擬dom構建的dom插入整個頁面中 1.這部分做了: 1.1.返回創建的 DOM 元素這也就是代碼中的'vnode.elm' 1.2.創建 vnode 對應的 DOM 元素 2.執行順序: 2.1.首先觸發用戶設置的 init 鉤子函數 2.2.如果選擇器是!,創建評論節點 2.3.如果選擇器為空,創建文本節點 2.4.如果選擇器不為空 2.4.1.解析選擇器,設置標簽的 id 和 class 屬性 2.4.2.執行模塊的 create 鉤子函數 2.4.3.如果 vnode 有 children,創建子 vnode 對應的 DOM,追加到 DOM 樹 2.4.4.如果 vnode 的 text 值是 string/number,創建文本節點并追擊到 DOM 樹 2.4.5.執行用戶設置的 create 鉤子函數 2.4.6.如果有用戶設置的 insert 鉤子函數,把 vnode 添加到隊列中 3.源碼位置:src/snabbdom.ts ~~~ >[danger] ##### 代碼分析 ~~~ts function createElm(vnode: VNode, insertedVnodeQueue: VNodeQueue): Node { let i: any, data = vnode.data; if (data !== undefined) { // 執行用戶設置的 init 鉤子函數 const init = data.hook ? .init; if (isDef(init)) { init(vnode); data = vnode.data; } } let children = vnode.children, sel = vnode.sel; if (sel === '!') { // 如果選擇器是!,創建評論節點 if (isUndef(vnode.text)) { vnode.text = ''; } vnode.elm = api.createComment(vnode.text!); } else if (sel !== undefined) { // 如果選擇器不為空 // 解析選擇器 // Parse selector const hashIdx = sel.indexOf('#'); const dotIdx = sel.indexOf('.', hashIdx); const hash = hashIdx > 0 ? hashIdx : sel.length; const dot = dotIdx > 0 ? dotIdx : sel.length; const tag = hashIdx !== -1 || dotIdx !== -1 ? sel.slice(0, Math.min(hash, dot)) : sel; const elm = vnode.elm = isDef(data) && isDef(i = data.ns) ? api.createElementNS(i, tag) : api.createElement(tag); // 在這之前都是對虛擬dom 的sel屬性進行解析,為了對提供的sel 選擇器而創建dom準備的 // 注意創建真實dom 有兩種一種是createElementNS這是創建svg,一種是createElement 創建普通dom // --------------------------------------------- if (hash < dot) elm.setAttribute('id', sel.slice(hash + 1, dot)); if (dotIdx > 0) elm.setAttribute('class', sel.slice(dot + 1).replace(/\./g, ' ')); // 執行模塊的 create 鉤子函數 for (i = 0; i < cbs.create.length; ++i) cbs.create[i](emptyNode, vnode); // 如果 vnode 中有子節點,創建子 vnode 對應的 DOM 元素并追加到 DOM 樹上 if (is.array(children)) { for (i = 0; i < children.length; ++i) { const ch = children[i]; if (ch != null) { api.appendChild(elm, createElm(ch as VNode, insertedVnodeQueue)); } } } else if (is.primitive(vnode.text)) { // 如果 vnode 的 text 值是 string/number,創建文本節點并追加到 DOM 樹 api.appendChild(elm, api.createTextNode(vnode.text)); } const hook = vnode.data!.hook; if (isDef(hook)) { // 執行用戶傳入的鉤子 create hook.create ? .(emptyNode, vnode); if (hook.insert) { // 把 vnode 添加到隊列中,為后續執行 insert 鉤子做準備 insertedVnodeQueue.push(vnode); } } } else { // 如果選擇器為空,創建文本節點 vnode.elm = api.createTextNode(vnode.text!); } // 返回新創建的 DOM return vnode.elm; } ~~~ >[info] ## addVnodes 和 removeVnodes 函數 ~~~ function addVnodes(parentElm: Node, before: Node | null, vnodes: Array<VNode>, startIdx: number, endIdx: number, insertedVnodeQueue: VNodeQueue) { for (; startIdx <= endIdx; ++startIdx) { const ch = vnodes[startIdx]; if (ch != null) { api.insertBefore(parentElm, createElm(ch, insertedVnodeQueue), before); } } } ~~~ ~~~ function removeVnodes(parentElm: Node, vnodes: Array<VNode>, startIdx: number, endIdx: number): void { for (; startIdx <= endIdx; ++startIdx) { let i: any, listeners: number, rm: () => void, ch = vnodes[startIdx]; if (ch != null) { // 如果 sel 有值 if (isDef(ch.sel)) { // 執行 destroy 鉤子函數(會執行所有子節點的 destroy 鉤子函數) invokeDestroyHook(ch); listeners = cbs.remove.length + 1; // 創建刪除的回調函數 rm = createRmCb(ch.elm as Node, listeners); for (i = 0; i < cbs.remove.length; ++i) cbs.remove[i](ch, rm); // 執行用戶設置的 remove 鉤子函數 if (isDef(i = ch.data) && isDef(i = i.hook) && isDef(i = i.remove)) { i(ch, rm); } else { // 如果沒有用戶鉤子函數,直接調用刪除元素的方法 rm(); } } else { // Text node // 如果是文本節點,直接調用刪除元素的方法 api.removeChild(parentElm, ch.elm as Node); } } } } function invokeDestroyHook(vnode: VNode) { let i: any, j: number, data = vnode.data; if (data !== undefined) { // 執行用戶設置的 destroy 鉤子函數 if (isDef(i = data.hook) && isDef(i = i.destroy)) i(vnode); // 調用模塊的 distroy 鉤子函數 for (i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode); // 執行子節點的 distroy 鉤子函數 if (vnode.children !== undefined) { for (j = 0; j < vnode.children.length; ++j) { i = vnode.children[j]; if (i != null && typeof i !== "string") { invokeDestroyHook(i); } } } } } function createRmCb(childElm: Node, listeners: number) { // 返回刪除元素的回調函數 return function rmCb() { if (--listeners === 0) { const parent = api.parentNode(childElm); api.removeChild(parent, childElm); } }; } ~~~
                  <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>

                              哎呀哎呀视频在线观看