Vue中fragment.js使用方法详解

发布时间 - 2026-01-11 00:05:44    点击率:

 大部分内容源自 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;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Vue  # fragment.js  # Vue中fragment.js使用方法小结  # React Fragment介绍与使用详解  # 使用newInstance()来实例化fragment并传递数据操作  # Fragment 占位组件不生成标签与路由组件lazyLoad案例  # 文档  # 多个  # 有兴趣  # 好用  # 创建一个  # 都不  # 就能  # 不需要  # 可以用  # 没人  # 要在  # 这段  # 一遍  # 不就  # 只有一个  # 忍者  # 如果说  # 可以看出  # 甚至连  # 在与 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  Python文件操作最佳实践_稳定性说明【指导】  如何挑选优质建站一级代理提升网站排名?  如何快速搭建二级域名独立网站?  音乐网站服务器如何优化API响应速度?  UC浏览器如何设置启动页 UC浏览器启动页设置方法  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  使用C语言编写圣诞表白程序  大学网站设计制作软件有哪些,如何将网站制作成自己app?  Laravel API资源类怎么用_Laravel API Resource数据转换  如何用低价快速搭建高质量网站?  Laravel如何处理异常和错误?(Handler示例)  做企业网站制作流程,企业网站制作基本流程有哪些?  Android GridView 滑动条设置一直显示状态(推荐)  linux写shell需要注意的问题(必看)  黑客入侵网站服务器的常见手法有哪些?  如何在IIS中新建站点并解决端口绑定冲突?  EditPlus中的正则表达式 实战(1)  如何用wdcp快速搭建高效网站?  如何在自有机房高效搭建专业网站?  如何在阿里云服务器自主搭建网站?  软银砸40亿美元收购DigitalBridge 强化AI资料中心布局  教你用AI将一段旋律扩展成一首完整的曲子  制作旅游网站html,怎样注册旅游网站?  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  Laravel如何操作JSON类型的数据库字段?(Eloquent示例)  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  如何用5美元大硬盘VPS安全高效搭建个人网站?  如何正确下载安装西数主机建站助手?  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  详解Oracle修改字段类型方法总结  韩国代理服务器如何选?解析IP设置技巧与跨境访问优化指南  Laravel中Service Container是做什么的_Laravel服务容器与依赖注入核心概念解析  网站建设要注意的标准 促进网站用户好感度!  Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  详解阿里云nginx服务器多站点的配置  敲碗10年!Mac系列传将迎来「触控与联网」双革新  Java类加载基本过程详细介绍  香港服务器租用费用高吗?如何避免常见误区?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  Python高阶函数应用_函数作为参数说明【指导】  php打包exe后无法访问网络共享_共享权限设置方法【教程】  百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  nodejs redis 发布订阅机制封装实现方法及实例代码  实例解析angularjs的filter过滤器