请首先阅读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数组!