jQuery.clean使用方法及思路分析

时间:2021-05-26

一、jQuery.clean使用方法
jQuery.clean( elems, context, fragment, scripts );
二、思路分析
1、处理参数context,确保其为文档根节点document
2、处理参数elems数组(循环遍历数组)
  2.1、elem为数字,转换为字符串
  2.2、elem为非法值,跳出本次循环
  2.3、elem为字符串
  2.4、字符串不存在实体编号或html标签,则创建文本节点
  2.5、字符串为实体编号或html标签
复制代码 代码如下:
创建一个div元素并插入到文档碎片中
处理xhtml风格标签
将elem包裹起来,并将包裹后的字符串作为div的innerHTML
如果包裹深度大于1,只留下第一层包裹元素
清除在ie6,7中空table标签自动加入的tbody
将在ie9以下浏览器中剔除的开头空白字符串作为div元素的第一个文本子节点
将elem重新赋值为div的子节点集合(nodeList对象),
移除本次循环中文档碎片中的div,保持下一次循环中干净的div元素    

2.3、如果elem为文本节点,则直接添加到要返回的ret数组中,否则将elem(nodeList对象)中的节点合并到数组
  2.4、修复在ie6、7中type为radio,checkbox类型的节点的选中状态(checked)失效的bug
3、处理参数fragment
  3.1、将ret中各节点添加到文档碎片fragment中
  3.2、提取节点中的script子节点,并将其添加到ret数组中,添加的script位置为其原父元素位置后面
4、返回ret数组
三、源码注释分析
1、函数中用到的变量及函数
复制代码 代码如下:
var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
wrapMap = {
option: [ 1, "<select multiple='multiple'>", "</select>" ],
legend: [ 1, "<fieldset>", "</fieldset>" ],
thead: [ 1, "<table>", "</table>" ],
tr: [ 2, "<table><tbody>", "</tbody></table>" ],
td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
area: [ 1, "<map>", "</map>" ],
_default: [ 0, "", "" ]
},
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
rtagName = /<([\w:]+)/,
rtbody = /<tbody/i,
rhtml = /<|&#?\w+;/,
rleadingWhitespace = /^\s+/,
rcheckableType = /^(?:checkbox|radio)$/,
rscriptType = /\/(java|ecma)script/i;
// 设置复选框checkbox或单选框radio表单元素的默认选中状态
function fixDefaultChecked( elem ) {
if ( rcheckableType.test( elem.type ) ) {
elem.defaultChecked = elem.checked;
}
}
// 创建一个安全的文档碎片
function createSafeFragment( document ) {
var list = nodeNames.split( "|" ),
safeFrag = document.createDocumentFragment(); // ie6,7,8浏览器把safeFrage作为HTMLDocument类型
// 针对ie9以下浏览器
if ( safeFrag.createElement ) {
while ( list.length ) {
safeFrag.createElement(
list.pop()
);
}
}
return safeFrag;
}
// 模拟ES5中Array的新功能
// 该函数API:http://pletely kills leading whitespace when innerHTML is used
// 在ie9以下浏览器中,字符串以空白字符串开头,将空白字符串作为div元素的第一个文本子节点
if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
}
// 获取已经处理完毕的div子节点集合(nodeList对象)
elem = div.childNodes;
// Take out of fragment container (we need a fresh div each time)
// 在下一次循环处理字符串数组项前,清除处理创建过的div元素
div.parentNode.removeChild( div );
}
}
// 如果elem为DOM节点(文本节点)
if ( elem.nodeType ) {
ret.push( elem );
}
// 将nodeList对象中节点合并到返回的数组中
else {
jQuery.merge( ret, elem );
}
}
// Fix #11356: Clear elements from safeFragment
if ( div ) {
elem = div = safe = null;
}
// Reset defaultChecked for any radios and checkboxes
// about to be appended to the DOM in IE 6/7 (#8060)
// 在ie6,7中,拥有checked属性的单选按钮,复选框在插入到其他标签后,选中状态会失效(下面代码修复该bug)
if ( !jQuery.support.appendChecked ) {
for ( i = 0; (elem = ret[i]) != null; i++ ) {
if ( jQuery.nodeName( elem, "input" ) ) {
fixDefaultChecked( elem );
} else if ( typeof elem.getElementsByTagName !== "undefined" ) {
jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
}
}
}
// Append elements to a provided document fragment
// 将ret数组中的各DOM节点插入到提供的文档碎片中
// 提取dom节点中的script节点,并添加到ret数组中,位置为其原父元素索引位置后
if ( fragment ) {
// Special handling of each script element
handleScript = function( elem ) {
// Check if we consider it executable
// 如果elem元素不存在type属性或者type值为javascript或者为ecmascript
if ( !elem.type || rscriptType.test( elem.type ) ) {
// Detach the script and store it in the scripts array (if provided) or the fragment
// Return truthy to indicate that it has been handled
return scripts ?
scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) :
fragment.appendChild( elem );
}
};
for ( i = 0; (elem = ret[i]) != null; i++ ) {
// Check if we're done after handling an executable script
if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) {
// Append to fragment and handle embedded scripts
// 将elem元素添加到文档碎片中并处理嵌入的脚本(script标签元素)
fragment.appendChild( elem );
if ( typeof elem.getElementsByTagName !== "undefined" ) {
// handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration
jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript );
// Splice the scripts into ret after their former ancestor and advance our index beyond them
// 将script标签添加到数组,位置为其原父元素索引位置后
ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
i += jsTags.length;
}
}
}
}
return ret;
}
});

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章