您的位置:首页 > Web前端 > JavaScript

javascript 包裹节点 提高效率

2010-02-20 00:00 555 查看
原理基本是这样,如果传入的是字符串,那么让它们变成一个元素节点,不过这元素节点也可以有许多层,在最内层把要包裹的元素放进。把字符串变成元素节点的方法有如下几个。
1,createElement,IE可以连元素属性也一起创建,但只能创建一层。
2,innerHTML,不过需要对原来的字符串进行处理,IE与FF都有许多意想不到的默认行为,可以为你多加一点东西或少加一点东西。
3,createContextualFragment,由于Opera的行为有点怪异,需要选中修改元素的位置。经日本人的测试,它转换字符串成节点的效率比innerHTML高多了,也安全多了,真是强者愈强,弱者愈弱。如果是传入元素节点,需要克隆一下,要不都变成wrapAll。如果是函数,把当前元素传进去,利用它的某些属性创建一个包裹元素。
最初的实验品(这里的wrapOuter相当于jQuery的wrap):
var parseHTML = function(str) { 
if(document.createRange){ 
var range = document.createRange() 
range.setStartAfter(document.body) 
return range.createContextualFragment(str) 
}else{ 
return document.createElement(str) 
} 
} 
var wrapOuter = function(target,html){ 
var wrap = parseHTML(html) ; 
target.parentNode.insertBefore(wrap,target); 
target.previousSibling.appendChild(target) 
}








.wrapper {
margin: 5px 5px 5px 5px;
padding: 5px 5px 5px 5px;
background-color:#dfe8f6;
border: 1px solid magenta;
}
.inner{
margin:1em;
height:20px;
background:#a9ea00
}
.border{
border:2px solid red;
}

包裹节点 by 司徒正美

window.onload = function(){var parseHTML = function(str) { if(document.createRange){ var range = document.createRange() range.setStartAfter(document.body) return range.createContextualFragment(str) }else{ return document.createElement(str) } } var wrapOuter = function(target,html){ var wrap = parseHTML(html) ; target.parentNode.insertBefore(wrap,target); target.previousSibling.appendChild(target) }var a = document.getElementById("target");
wrapOuter(a,"")
}




目标节点




[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

发现在Opera中出了些问题,range.setStartAfter(document.body)要改成我们的目标元素才行。再者,将插入包裹元素的方式由insertBefore改为replaceChild,提高效率。
var wrapOuter = function(target,html){ 
var wrap = html 
if(Object.prototype.toString.call(html) === "[object String]"){ 
if(document.createRange){ 
var range=document.createRange(); 
range.selectNodeContents(target); 
wrap = range.createContextualFragment(html).firstChild; 
}else { 
wrap = document.createElement(str); 
} 
} 
target.parentNode.replaceChild(wrap,target); 
wrap.appendChild(target) 
}








.wrapper {
margin: 5px 5px 5px 5px;
padding: 5px 5px 5px 5px;
background-color:#dfe8f6;
border: 1px solid magenta;
}
.inner{
margin:1em;
height:20px;
background:#a9ea00
}
.border{
border:2px solid red;
}

包裹节点 by 司徒正美

window.onload = function(){
var wrapOuter = function(target,html){
var wrap = html
if(Object.prototype.toString.call(html) === "[object String]"){
if(document.createRange){
var range=document.createRange();
range.selectNodeContents(target);
wrap = range.createContextualFragment(html).firstChild;
}else {
wrap = document.createElement(str);
}
}
target.parentNode.replaceChild(wrap,target);
wrap.appendChild(target)
}
var a = document.getElementById("target");
wrapOuter(a,"")
}




目标节点




[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
//给每个匹配元素都增加一个父元素(包裹元素), 
wrap:function(html){//html可以是元素节点,也可以是html片断 
var _wrap = function(target,html){ 
var wrap; 
if(is(html,"String")){ 
if(document.createRange){ 
var range=document.createRange(); 
range.selectNodeContents(target); 
wrap = range.createContextualFragment(html).firstChild; 
}else { 
wrap = document.createElement(html); 
} 
}else if(html.nodeType){ 
wrap = html.cloneNode(true) 
} 
target.parentNode.replaceChild(wrap,target); 
wrap.appendChild(target) 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
},

把创建包裹元素的方法抽象出来:
var _parseHTML = function(el,html){ 
var wrap = html ; 
if(doc.createRange){ 
var range=doc.createRange(); 
range.selectNodeContents(el); 
var wrap = range.createContextualFragment(html).firstChild; 
range.detach(); 
return wrap; 
}else { 
return dom.parseHTML(html); 
} 
} 
//给每个匹配元素都增加一个父元素(包裹元素), 
wrap:function(html){//html可以是元素节点,也可以是html片断 
var _wrap = function(target,html){ 
var wrap = html ; 
if(!wrap.nodeType){ 
wrap = dom._parseHTML(target,html); 
}else{ 
wrap = html.cloneNode(true) 
} 
target.parentNode.replaceChild(wrap,target); 
wrap.insertBefore(target,null) 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
}, 
wrapInner:function(html){ 
var _wrap = function(target,html){ 
var wrap = html ; 
if(!wrap.nodeType){ 
wrap = dom._parseHTML(target,html); 
}else{ 
wrap = html.cloneNode(true) 
} 
target.insertBefore(wrap,target.firstChild); 
for(var i=1,n=target.childNodes.length;i<n;i++){ 
wrap.appendChild(target.childNodes[i],null) 
} 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
}, 
//用一个标签包裹所有匹配元素 
//做法:在第一个匹配元素上添加一个父元素(包裹),然后把其他匹配元素都转移到此父元素中来 
//wrapAll(html) wrapAll(elem) 
wrapAll:function(html){ 
var wrap = html; 
if(!wrap.nodeType) 
wrap = dom._parseHTML(this[0],html); 
this[0].parentNode.replaceChild(wrap,this[0]); 
return this.each(function(el){ 
wrap.insertBefore(el,null); 
}); 
},

jQuery官网看一下,发现它的包裹节点的方法升级了,每次可以包裹许多层了,而我的每次只能包一层。于是决定调用我原来的parseHTML方法,见这里
var wrap = function(html){//html可以是元素节点,也可以是html片断 
var _wrap = function(target,html){ 
var wrap = html ; 
if(!wrap.nodeType){ 
if(doc.createRange){ 
var range=doc.createRange(); 
range.selectNodeContents(target); 
wrap = range.createContextualFragment(html).firstChild; 
}else{ 
wrap = dom.parseHTML(html,null,true).firstChild 
} 
}else{ 
wrap = html.cloneNode(true) 
} 
target.parentNode.replaceChild(wrap,target); 
while ( wrap.firstChild && wrap.firstChild.nodeType === 1 ) { 
wrap = wrap.firstChild; 
} 
wrap.insertBefore(target,null) 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
} 
//把每一个匹配元素的子节点都用东西包裹起来 
var wrapInner = function(html){ 
var _wrap = function(target,html){ 
var wrap = html ; 
if(!wrap.nodeType){ 
wrap = dom.parseHTML(html,null,true).firstChild 
}else{ 
wrap = html.cloneNode(true) 
} 
target.insertBefore(wrap,target.firstChild); 
while ( wrap.firstChild && wrap.firstChild.nodeType === 1 ) { 
wrap = wrap.firstChild; 
} 
for(var i=1,n=target.childNodes.length;i<n;i++){ 
wrap.appendChild(target.childNodes[i],null) 
} 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
} 
//用一个标签包裹所有匹配元素 
//做法:在第一个匹配元素上添加一个父元素(包裹),然后把其他匹配元素都转移到此父元素中来 
//wrapAll(html) wrapAll(elem) 
var wrapAll = function(html){ 
var wrap = html; 
if(!wrap.nodeType){ 
if(doc.createRange){ 
var range = doc.createRange(); 
range.selectNodeContents(this[0]); 
wrap = range.createContextualFragment(html).firstChild; 
}else{ 
wrap = dom.parseHTML(html,null,true).firstChild 
} 
} else{ 
wrap = html.cloneNode(true) 
} 
this[0].parentNode.replaceChild(wrap,this[0]); 
while ( wrap.firstChild && wrap.firstChild.nodeType === 1 ) { 
wrap = wrap.firstChild; 
} 
return this.each(function(el){ 
wrap.insertBefore(el,null); 
}); 
}

发现有许多重复代码,再抽象一下,对外人来说,彻底的不知所云,想必jQuery也是这样一步步搞到晦涩难懂的。
dom.mixin(dom[fn],(function(){ 
var wrapHelper = function(target,html ){ 
var wrap = html ; 
if(!wrap.nodeType){ 
if(document.createRange){ 
var range=dom.doc.createRange(); 
range.selectNodeContents(target); 
wrap = range.createContextualFragment(html).firstChild; 
} else{ 
wrap = dom.parseHTML(html,null,true).firstChild 
} 
}else{ 
wrap = html.cloneNode(true) 
} 
var insertor = wrap; 
while ( insertor.firstChild && insertor.firstChild.nodeType === 1 ) { 
insertor = insertor.firstChild; 
} 
return [wrap,insertor] 
} 
//用一个标签包裹所有匹配元素 
//做法:在第一个匹配元素上添加一个父元素(包裹),然后把其他匹配元素都转移到此父元素中来 
//wrapAll(html) wrapAll(elem) 
var wrapAll = function(html){ 
if ( dom.isFunction( html ) ) { 
return this.each(function(el,index) { 
dom(this).wrapAll( html.call(this, index)); 
}); 
} 
var arr = wrapHelper(this[0],html); 
var wrap = arr[0],insertor =arr[1]; 
this[0].parentNode.replaceChild(wrap,this[0]); 
return this.each(function(el){ 
insertor.insertBefore(el,null); 
}); 
} 
//给每个匹配元素都增加一个父元素(包裹元素), 
var wrap= function( html ) { 
return this.each(function() { 
dom( this ).wrapAll( html ); 
}); 
} 
//把每一个匹配元素的子节点都用东西包裹起来 
var wrapInner = function(html){ 
var _wrap = function(target,html){ 
var arr = wrapHelper(target,html); 
var wrap = arr[0],insertor =arr[1]; 
target.insertBefore(wrap,target.firstChild); 
for(var i=1,n=target.childNodes.length;i<n;i++){ 
insertor.appendChild(target.childNodes[i],null) 
} 
} 
if(is(html,"Function")){ 
return this.each(function(el,index){ 
_wrap(el, html.call(el,index)); 
}); 
} 
return this.each(function(el){ 
_wrap(el,html) 
}); 
} 
return { 
wrapAll:wrapAll, 
wrap:wrap, 
wrapInner:wrapInner 
} 
})());

unwrap方法以后再说!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: