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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [TOC] * * * * * ## 1 源代碼文件 ### 1-1 解析實現 ~~~ src\strategy\lexer.js ~~~ ### 1-2 解析生成 ~~~ src\vdom\ ~~~ ## 2 流程分析 ### 2-1 節點內容解析 ~~~ src\strategy\lexer.js function lexer(text, recursive) { // 所有生成節點數組 var nodes = [] // recursive參數使用 true 解析子節點時調用 if (recursive && !rbind.test(text)) { return nodes } // recursive參數使用 false 文本數組存儲??1,??2,這里實現嵌套 if (!recursive) { text = text.replace(rstring, dig) } // 反復迭代解析 do { // 初始化解析狀態outerHTML,node var outerHTML = '' var node = false //創建文本虛擬節點 VText var match = text.match(rtext) if (match) { outerHTML = match[0] node = new VText(outerHTML.replace(rfill, fill)) } //創建注釋虛擬節點 VComment if (!node) { match = text.match(rcomment) if (match) { outerHTML = match[0] node = new VComment(match[1].replace(rfill, fill)) // 移除緊挨著<!--ms-for-end:xxxx-->前的空白節點 // 注釋節點空白清除 var nodeValue = node.nodeValue if (rspBeforeForEnd.test(nodeValue)) { var sp = nodes[nodes.length - 1] if (sp && sp.type === '#text' && rsp.test(sp.nodeValue)) { nodes.pop() } } } } //創建閉標簽虛擬節點 if (!node) { // 閉合節點 match = text.match(rfullTag) if (match) { //貪婪匹配 outerHTML,可能匹配過多 outerHTML = match[0] //節點類型 var type = match[1].toLowerCase() outerHTML = clipOuterHTML(outerHTML, type) //節點屬性 match = outerHTML.match(rvoidTag) var props = {} if (match[2]) { handleProps(match[2], props) } //節點innerHTML var innerHTML = outerHTML.slice(match[0].length, (type.length + 3) * -1) // 節點組織 node = { type: type, props: props, template: innerHTML.replace(rfill, fill).trim(), children: [] } node = modifyProps(node, innerHTML, nodes) } } //創建自閉合標簽虛擬節點 if (!node) { match = text.match(rvoidTag) if (match) { // outerHTML = match[0] // 節點類型 type = match[1].toLowerCase() // 節點屬性 props = {} if (match[2]) { handleProps(match[2], props) } // 節點結點 node = { type: type, props: props, template: '', children: [], isVoidTag: true } modifyProps(node, '', nodes) } } if (node) { // 創建節點成功 保存到數組 nodes.push(node) text = text.slice(outerHTML.length) if (node.type === '#comment' && rspAfterForStart.test(node.nodeValue)) { node.signature = makeHashCode('for') //移除緊挨著<!--ms-for:xxxx-->后的空白節點 text = text.replace(rleftSp, '') } } else { // 創建節點失敗 直接跳出 break } } while (1); // 非遞歸的情況 if (!recursive) { maps = {} } return nodes } ~~~ > text:待解析節點內容 > recursive:是否屬于遞歸解析,節點內解析子節點 * * * * * > 準備返回節點數組 > 檢查recursive,是否屬于子節點解析 > 循環解析主體 > 1 虛擬文本節點匹配解析Vtext > 2 虛擬注釋節點匹配解析VComment > 3 雙標簽生成虛擬節點VElement > 4 單標簽生成虛擬節點VElement > 5 元素節點解析的modifyProps()遞歸調用lexer()解析子節點 ### 2-2 虛擬節點創建 ~~~ var match = text.match(rtext) node = new VText(outerHTML.replace(rfill, fill)) ~~~ > 虛擬文本節點 ~~~ match = text.match(rcomment) node = new VComment(match[1].replace(rfill, fill)) ~~~ > 虛擬注釋節點 ~~~ match = text.match(rfullTag) node = modifyProps(node, innerHTML, nodes) match = text.match(rvoidTag) modifyProps(node, '', nodes) ~~~ > 虛擬元素節點 ### 2-3 handleProps(str, props)屬性操作 ~~~ var ramp = /&amp;/g var rnowhite = /\S+/g var rquote = /&quot;/g var rnogutter = /\s*=\s*/g function handleProps(str, props) { str.replace(rnogutter, '=').replace(rnowhite, function (el) { var arr = el.split('='), value = arr[1] || '', name = arr[0].toLowerCase() if (arr.length === 2) { if (value.indexOf('??') === 0) { value = value.replace(rfill, fill). slice(1, -1). replace(ramp, '&'). replace(rquote, '"') } } props[name] = value }) } ~~~ ### 2-4 modifyProps(node, innerHTML, nodes)元素節點修正與遞歸解析 ~~~ function modifyProps(node, innerHTML, nodes) { // 節點類型 var type = node.type if (node.props['ms-skip']) { // 包含ms-skip屬性的節點 node.skipContent = true } else { // 非包含ms-skip屬性的節點 // 根據節點屬性操作 switch (type) { case 'style': case 'script': case 'noscript': case 'template': case 'textarea': node.skipContent = true if (type === 'textarea') { node.props.type = 'textarea' } break case 'input': if (!node.props.type) { node.props.type = 'text' } case 'xmp': node.children.push(new VText(node.template)) break case 'option': node.children.push(new VText(trimHTML(node.template))) break default: // 遞歸解析子節點 if (!node.isVoidTag) { var childs = lexer(innerHTML, true) node.children = childs // 如果是table節點 if (type === 'table') { addTbody(node.children) } } break } // for類型表達式 var forExpr = node.props['ms-for'] if (forExpr) { nodes.push({ type: '#comment', nodeValue: 'ms-for:' + forExpr, signature: makeHashCode('for') }) delete node.props['ms-for'] nodes.push(node) node = { type: '#comment', nodeValue: 'ms-for-end:' } } } return node } ~~~ ### 2-5 clipOuterHTML(matchText, type) 截取OuterHTML ~~~ var openStr = '(?:\\s+[^>=]*?(?:=[^>]+?)?)*>' var tagCache = {}// 緩存所有匹配開標簽閉標簽的正則 var rchar = /./g var regArgs = avalon.msie < 9 ? 'ig' : 'g'//IE6-8,標簽名都是大寫 function clipOuterHTML(matchText, type) { var opens = [] var closes = [] // 開標簽與閉標簽的緩存 var ropen = tagCache[type + 'open'] || (tagCache[type + 'open'] = new RegExp('<' + type + openStr, regArgs)) var rclose = tagCache[type + 'close'] || (tagCache[type + 'close'] = new RegExp('<\/' + type + '>', regArgs)) /* jshint ignore:start */ //注意,頁面有時很長,b的數值就很大,如 //000000000<000000011>000000041<000000066>000000096<000000107> matchText.replace(ropen, function (_, b) { //取得所有開標簽的位置 opens.push(('0000000000' + b + '<').slice(-10)) return _.replace(rchar, '1') }).replace(rclose, function (_, b) { //取得所有閉標簽的位置 closes.push(('0000000000' + b + '>').slice(-10)) }) /* jshint ignore:end */ /*<div> <div>01</div> <div>02</div> </div> <div>222</div> <div>333</div> 會變成 000< 005< 012> 018< 025> 031> 037< 045> 051< 059> 再變成 <<><>> <> <> 最后獲取正確的>的索引值,這里為<<><>>的最后一個字符,*/ var pos = opens.concat(closes).sort() var gtlt = pos.join('').replace(rnumber, '') var k = 0, last = 0 for (var i = 0, n = gtlt.length; i < n; i++) { var c = gtlt.charAt(i) if (c === '<') { k += 1 } else { k -= 1 } if (k === 0) { last = i break } } // (</>為三個字符) var findex = parseFloat(pos[last]) + type.length + 3 //取得正確的outerHTML return matchText.slice(0, findex) } ~~~ ### 2-7 addTbody(nodes) table修正 ~~~ function addTbody(nodes) { var tbody, needAddTbody = false, count = 0, start = 0, n = nodes.length for (var i = 0; i < n; i++) { var node = nodes[i] if (!tbody) { if (node.type === 'tr') { tbody = { type: 'tbody', template: '', children: [], props: {} } tbody.children.push(node) needAddTbody = true if (start === 0) start = i nodes[i] = tbody } } else { if (node.type !== 'tr' && node.type.charAt(0) !== "#") { tbody = false } else { tbody.children.push(node) count++ nodes[i] = 0 } } } if (needAddTbody) { for (i = start; i < n; i++) { if (nodes[i] === 0) { nodes.splice(i, 1) i-- count-- if (count === 0) { break } } } } } ~~~ ## 4 總結 ### 4-1 意義 解析dom內容為虛擬dom ### 4-2 思路 遞歸調用lexer()解析節點 ### 4-3 其他操作 [附:虛擬DOM](http://www.hmoore.net/zmwtp/avalon2/137892)
                  <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>

                              哎呀哎呀视频在线观看