Node.prototype.appendChildPlus()
写于:2017-1-2 | 更新于:2017-1-3
概述
appendChild方法的缺点有两个:
不能传多个参数
参数只能是节点对象
这里给Node.prototype添加一个方法,名称为:appendChildPlus,可以认为是appendChild的加强版,特点如下:
参数可以是html字符串和节点对象
可以传多个参数
script标签字符串和新建的script节点对象插入文档以后可以正常运行
所有参数是一起插入指定节点的,而不是一个一个插入。
源代码
// appendChildPlus.js
/**
* Created by jszhou on 2017/1/2.
* updated by jszhou on 2017/1/3.
*/
(function () {
/**
* 把类数组对象转换为数组。
*/
var toArray = Array.from || function (arg) {
return Array.prototype.slice.call(arg);
};
/**
* 判断参数是否为节点对象。
* @param {?} arg
* @return {boolean}
*/
function isNode(arg) {
return arg instanceof Node;
}
/**
* 判断参数是否为script节点对象。
* @param {?} arg
* @return {boolean}
*/
function isScript(arg) {
return isNode(arg) && arg.nodeName.toLowerCase() === 'script';
}
/**
* 复制script节点对象,复制以后script标签的内容可以运行。
* @param {object} script script节点对象
* @return {object} 返回新的script节点对象
*/
function copyScript(script) {
var newScript = document.createElement('script');
// 复制属性
toArray(script.attributes).forEach(function (item) {
newScript.setAttribute(item.nodeName, item.nodeValue);
});
newScript.innerHTML = script.innerHTML;
return newScript;
}
/**
* 替代script节点对象,替代以后script标签的内容可以运行。
* @param {object} node 节点对象
* @return {object} 返回script被替代的节点对象(script节点对象被替代成可以运行的)
*/
function replaceAllScript(node) {
Array.prototype.forEach.call(node.childNodes, function (item) {
// 如果是script节点对象,则替代为可运行的script节点对象
if(isScript(item)) {
item.parentNode.replaceChild(copyScript(item), item);
return;
}
// 递归
if(item.childNodes.length > 0){
replaceAllScript(item);
}
});
return node;
}
/**
* 字符串转成文档片段节点对象。
* @param {String} str 字符串,可以包含script标签,转换完插入文档以后可以运行。
* @return {Object} 返回文档片段节点对象
*/
function strToNode(str) {
var docFrag = document.createDocumentFragment(),
div = document.createElement('div');
div.innerHTML = str;
toArray(replaceAllScript(div).childNodes).forEach(function (item) {
docFrag.appendChild(item);
});
return docFrag;
}
/**
* 用于扩展appendChild方法。可以传入html字符串和节点对象,可以传多个参数。
* 如果html字符串中有script标签,插入以后可以正常运行。
* 注意,所有参数是一起插入指定节点的,而不是一个一个插入。
*/
Node.prototype.appendChildPlus = function () {
var docFrag = document.createDocumentFragment();
toArray(arguments).forEach(function (arg) {
docFrag.appendChild(isNode(arg) ? arg : strToNode(String(arg)));
});
this.appendChild(docFrag);
};
})();
示例代码
// extend.js
var wrap = document.querySelector('.js-wrap'),
deepScript = '<div><script>wrap.append("deepScript");</script></div>',
newScriptNode = document.createElement('script'),
outerScript = '<script src="./outerScript.js"></script>';
newScriptNode.textContent = 'wrap.append("newScriptNode");';
wrap.appendChildPlus(deepScript, newScriptNode, outerScript, '<div>nihao</div>');
// outerScript.js
wrap.append('outerScript');
<!--extend.html-->
<!--运行前-->
<div class="js-wrap"></div>
<script src="../appendChildPlus.js"></script>
<script src="./extend.js"></script>
<!--运行后-->
<div class="js-wrap">
<div><script>wrap.append("deepScript");</script></div>
<script>wrap.append("newScriptNode");</script>
<script src="./outerScript.js"></script>
<div>nihao</div>
deepScript
newScriptNode
outerScript
</div>
<script src="../appendChildPlus.js"></script>
<script src="./extend.js"></script>
更多
本扩展的markdown和demo源文件在github上,点击这里查看
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。