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上,点击这里检察