请首先阅读buildFrament以及正则表达式相关源码
源码如下:
//将字符串转化为节点数组!通过log可以知道
var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
jQuery.parseHTML1 = function( data, context, keepScripts ) {
if ( !data || typeof data !== "string" ) {
return null;
}
//只有两个参数的时候,第二个就是是否保存script标签,这时候context就没有传进来!
if ( typeof context === "boolean" ) {
keepScripts = context;
context = false;
}
//如果只有两个参数那么context就是document对象!
context = context || document;
//如果不是单个标签那么parsed就是null,所谓的单个标签就是<div/>或者<div></div>但是<div>hello</div>不满足!
var parsed = rsingleTag.exec( data ),
//如果keepScripts是false,那么scripts就是
scripts = !keepScripts && [];
// Single tag
if ( parsed ) {
//如果是单个标签就调用相应的createElement方法,默认上下文是document!
return [ context.createElement( parsed[1] ) ];
}
//如果不是单个标签就调用buildFragment方法,把html字符串传入,同时上下文也传入,第三个参数就是scripts!
//如果paseHTML的第三个参数是false,那么这里的scripts就是一个数组,传递到buildFragment中会把所有的script标签放在里面
//所以就要收到移除!
parsed = jQuery.buildFragment( [ data ], context, scripts );
if ( scripts && scripts.length ) {
jQuery( scripts ).remove();
}
//buildFragment返回的是文档碎片,所以要变成数组,调用merge方法!
return jQuery.merge( [], parsed.childNodes );
};
var result1=jQuery.parseHTML1("<div>我是内容1</div><script>alert('我是解析出来的js');<\/script><div>我是内容2</div>",document,true);
console.log(result1);
//通过firebug可以看到script标签已经添加到页面中了!但是必须添加到页面中才会执行!
$.each(result1,function(i,elem)
{
$(elem).appendTo($("body"));
})
如果我们在调用parseHTML时候传入的第三个参数是false,那么就和下面的逻辑是一样的
//如果我们parseHTML时候传入了false表示不保存script标签,那么所有的script标签全部在scripts这个数组中!
var scripts = true && [];
//创建了一个文档碎片!
var parsed = jQuery.buildFragment( [ "<div>我是内容1</div><script>alert('我是解析出来的js');<\/script><div>我是内容2</div>" ], document, scripts );
console.log(parsed);
//从保存script的集合scripts中移除所有的scripts
if ( scripts && scripts.length ) {
//scripts中放的全部是DOM,所以jQuery(scripts)是把其转化为jQuery对象!
jQuery( scripts ).remove();
}
console.log(parsed);
这时候如果没有remove方法的调用,第一个log打印的文档碎片是有script元素的,但是因为后面调用remove方法,所以这个集合中的script元素全部移除了!如果我们传入true表示会保存script元素,所以这时候我们不需要给buildFrament传入这个数组,因为没有意义,我们后面不需要单独操作这个集合移除所有的script!
在init方法中有这样一段代码:
jQuery.merge( this, jQuery.parseHTML(match[1],context && context.nodeType ? context.ownerDocument || context : document,true) );
这样造成的结果就是我们我们创建script标签添加到页面中,如:
$("<script>alert('我被用于创建script标签')<\/script>").appendTo($("body"));
因为这个参数显然满足第一个字符是<,最后一个字符是>,而且长度大于3!
note:
(1)如果把上面的parseHTML1中最后一个参数修改为false那么传入buildFrament函数的就是一个数组,这个数组会放所有的script标签,所以返回的时候会判断这个数组的length,如果有script集合,那么必须手动移除!
(2)这个方法的作用是,如果是<div/>就创建相应的DOM元素,否则就创建一个文档碎片!但是函数的返回值始终是一个DOM数组!