Vue中fragment.js使用方法詳解,vuefragment.js

來源:互聯網
上載者:User

Vue中fragment.js使用方法詳解,vuefragment.js

 大部分內容來源自 jQuery,當然,同時也參考了 component/domify ,如果有興趣去這翻閱原始的代碼,可以到 jQuery 中尋找 wrapMap;至於 domify,直接到 github 搜尋即可,相關項目類容很少,直接看 index.js 就行了。

createDocumentFragment

如果要在一個節點上一次性插入多個元素怎麼辦,比如說一次插入 10000 個節點?

最簡單粗暴的方式就是:

var parent = document.getElementById('parent');for(var i = 0; i < 10000; i++) { var child = document.createElement('div'); var text = document.createTextNode('' + i); child.appendChild(text); parent.appendChild(child);}

不過眾所周知的原因,對 DOM 反覆操作會導致頁面重繪、迴流,效率非常低,而且頁面可能會被卡死,這段代碼基本是沒人用的。

如果分段來進行 DOM 操作呢,這樣就能避免卡死頁面了,js 忍者秘籍裡面提到過可以用 setTimeout 來改進:

var i = 0, max = 10000;setTimeout(function addNodes() { for(var step = i + 500; i < step; i++) {  var child = document.createElement('div');  child.appendChild(document.createTextNode('' + i));  div.appendChild(child); } if(i < max) {  setTimeout(addNodes, 0); }}, 0);

當然,更多能想到的方式應該是,在記憶體中直接動作節點,所有節點都湊在一起之後再跟 DOM 樹進行互動,把所有節點都串在一個 div 上,然後再把 div 掛到 DOM 樹上:

var parent = document.getElementById('parent');var div = document.createElement('div');for(var i = 0; i < 10000; i++) { var child = document.createElement('div'); var text = document.createTextNode('' + i); child.appendChild(text); div.appendChild(child);}parent.appendChild(div);

如上,只跟 DOM 樹互動一次,效能方面肯定是大有改善的,不過額外插入了一個 div,如果說不是跟div之類的節點進行互動呢,比如在 table 中插入 th、td?

這時候,createDocumentFragment 就該出馬了,翻譯過來叫“文檔片段”,按MDN的描述

DocumentFragments 是一些 DOM 節點。它們不是 DOM 樹的一部分。通常的使用情境是建立一個文檔片段,然後將建立的 DOM 元素插入到文檔片段中,最後把文檔片段插入到 DOM 樹中。在 DOM 樹中,文檔片段會被替換為它所有的子項目。

因為文檔片段存在與記憶體中,並不在 DOM 樹中,所以將子項目插入到文檔片段時不會引起頁面迴流(對元素位置和幾何上的計算)。因此,使用文檔片段 document fragments 通常會起到最佳化效能的作用。

簡單來說,就是上面一個例子的不需要 div 中轉版本,插入的時候,直接用其子項目替換其本身,非常完美。

雖然說,“好用的都不通用”(特別是針對某公司瀏覽器),不過這個好用的東西,甚至連 IE6 都支援。

具體代碼大概就長這樣:

var parent = document.getElementById('parent');var frag = document.createDocumentFragment();for(var i = 0; i < 10000; i++) { var child = document.createElement('div'); var text = document.createTextNode('' + i); child.appendChild(text); frag.appendChild(child);}parent.appendChild(frag);

具體效能方面的測試,有興趣的可以把所有代碼都跑一遍。

innerHTML

把一長串字串轉換為對應的 DOM 節點,正常而言,首先想到的肯定是 innerHTML。大概流程就是,先建立一個 div 節點,然後 div.innerHTML = str,根據需要把 div 的 children 取出來放到該放的地方去,div 本身給扔了。

如果想單獨產生一個 th-節點呢?

試試上面的流程:

var div = document.createElement('div');div.innerHTML = '<th>xxx</th>';console.log(div);

實際輸出是(chrome 下):

<div>xxx</div>

並沒有得到想要的:

<div><th>xxx</th></div>

對於這樣的結果是可以理解的,畢竟一個 th 放到 div 裡面,怎麼看都不對,直接把外圍的標籤去掉,內容扔到 div 裡面也是相當智能的。

不過架不住,有時候就是要擷取一個 th-節點。

其實也好辦,寫全了不就得了:

var node = document.createElement('div');node.innerHTML = '<table><tbody><tr><th>xxx</th></tr></tbody></table>';// 把外面的幾層皮扒掉就是想要的 th 了var depth = 3;while(depth--) { node = node.lastChild; }console.log(node.firstChild);

可以看出,結果正是所想要的。

fragment.js

// 需要單獨處理的一些特殊節點var map = { legend : [1, '<fieldset>', '</fieldset>'], tr : [2, '<table><tbody>', '</tbody></table>'], col : [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'], _default : [0, '', '']};map.td = map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];map.option = map.optgroup = [1, '<select multiple="multiple">', '</select>'];map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '<table>', '</table>']map.text = map.circle = map.ellipse = map.line = map.path = map.polygon = map.polyline = map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];var TAG_RE = /<([\w:]+)/;module.exports = function(templateString) { var frag = document.createDocumentFragment(),  m = TAG_RE.exec(templateString); // 單純字串的情況 if(!m) {  frag.appendChild(document.createTextNode(templateString);  return frag; } var tag = m[1],  wrap = map[tag] || map._default,  depth = wrap[0],  prefix = wrap[1],  suffix = wrap[2],  node = document.createElement('div'); // 拼接節點字串 node.innerHTML = prefix + templateString.trim() + suffix; // 去除外包裹層,只留字串轉化的節點 while(depth--) node = node.lastChild; // 只有一個節點的情況 if(node.firstChild === node.lastChild) {   frag.appendChild(node.firstChild);  return frag; } // 多個節點,依序添加到 frag var child; while(child = node.firstChild) {  frag.appendChild(child); } return frag;}

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.