深入理解javascript动态插入技术_javascript技巧
IE的innerHTML By 司徒正美
另一个可恶的地方是,在IE中以下元素的innerHTML是只读的:col、 colgroup、frameset、html、 head、style、table、tbody、 tfoot、 thead、title 与 tr。为了收拾它们,Ext特意弄了个insertIntoTable。insertIntoTable就是利用DOM的insertBefore与appendChild来添加,情况基本同jQuery。不过jQuery是完全依赖这两个方法,Ext还使用了insertAdjacentHTML。为了提高效率,所有类库都不约而同地使用了文档碎片。基本流程都是通过div.innerHTML提取出节点,然后转移到文档碎片上,然后用insertBefore与appendChild插入节点。对于火狐,Ext还使用了createContextualFragment解析文本,直接插入其目标位置上。显然,Ext的比jQuery是快许多的。不过jQuery的插入的不单是HTML片断,还有各种节点与jQuery对象。下面重温一下jQuery的工作流程吧。
append: function() {
//传入arguments对象,true为要对表格进行特殊处理,回调函数
return this.domManip(arguments, true, function(elem){
if (this.nodeType == 1)
this.appendChild( elem );
});
},
domManip: function( args, table, callback ) {
if ( this[0] ) {//如果存在元素节点
var fragment = (this[0].ownerDocument || this[0]).createDocumentFragment(),
//注意这里是传入三个参数
scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment ),
first = fragment.firstChild;
if ( first )
for ( var i = 0, l = this.length; i callback.call( root(this[i], first), this.length > 1 || i > 0 ?
fragment.cloneNode(true) : fragment );
if ( scripts )
jQuery.each( scripts, evalScript );
}
return this;
function root( elem, cur ) {
return table && jQuery.nodeName(elem, "table") && jQuery.nodeName(cur, "tr") ?
(elem.getElementsByTagName("tbody")[0] ||
elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
elem;
}
}
//elems为arguments对象,context为document对象,fragment为空的文档碎片
clean: function( elems, context, fragment ) {
context = context || document;
// !context.createElement fails in IE with an error but returns typeof 'object'
if ( typeof context.createElement === "undefined" )
//确保context为文档对象
context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
//如果文档对象里面只有一个标签,如
//我们大概可能是在外面这样调用它$(this).append("
//这时就直接把它里面的元素名取出来,用document.createElement("div")创建后放进数组返回
if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
var match = /^$/.exec(elems[0]);
if ( match )
return [ context.createElement( match[1] ) ];
}
//利用一个div的innerHTML创建众节点
var ret = [], scripts = [], div = context.createElement("div");
//如果我们是在外面这样添加$(this).append("
//jQuery.each按它的第四种支分方式(没有参数,有length)遍历aguments对象,callback.call( value, i, value )
jQuery.each(elems, function(i, elem){//i为索引,elem为arguments对象里的元素
if ( typeof elem === "number" )
elem += '';
if ( !elem )
return;
// Convert html string into DOM nodes
if ( typeof elem === "string" ) {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(/(]*?)\/>/g, function(all, front, tag){
return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
all :
front + ">" + tag + ">";
});
// Trim whitespace, otherwise indexOf won't work as expected
var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();
var wrap =
// option or optgroup
!tags.indexOf("
!tags.indexOf("
tags.match(/^ [ 1, "
!tags.indexOf("
// matched above
(!tags.indexOf("
!tags.indexOf("
// IE can't serialize and
// Move to the right depth
while ( wrap[0]-- )
div = div.lastChild;
//处理IE自动插入tbody,如我们使用$('')创建HTML片断,它应该返回
//'',而IE会返回'
if ( !jQuery.support.tbody ) {
// String was a
推荐阅读
-
JavaScript可否多线程? 深入理解JavaScript定时机制_javascript技巧
-
深入理解JavaScript系列(29):设计模式之装饰者模式详解_javascript技巧
-
深入理解JavaScript系列(27):设计模式之建造者模式详解_javascript技巧
-
JavaScript this 深入理解_javascript技巧
-
深入理解JavaScript定时机制_javascript技巧
-
JavaScript词法作用域与调用对象深入理解_javascript技巧
-
深入理解Javascript中this的作用域_javascript技巧
-
深入理解JavaScript系列(16) 闭包(Closures)_javascript技巧
-
深入理解JavaScript系列(27):设计模式之建造者模式详解_javascript技巧
-
JavaScript动态插入script的基本思路及实现函数_javascript技巧
网友评论
文明上网理性发言,请遵守 新闻评论服务协议
我要评论