0 Comments

生成DOM元素

发布于:2013-05-31  |   作者:广州网站建设  |   已聚集:人围观
生成DOM元素

jQuery.fn.init()构造函数能够构建jQuery对象,并把匹配的DOM元素存储在jQuery对象内部集合中。jQuery.fn.init()构造函数可以接收单个的DOM元素,也可以接收DOM集合。如果接收的是字符串型ID值,则直接在文档中查找对应的DOM元素,并把它传递给jQuery对象;如果接收的是字符串型HTML片段,则需要把这个字符串片段生成DOM元素。下面我们将重点分析jQuery是如何把HTML片段生成DOM元素的。

在2.3.3节中,我们可以看到jQuery.fn.init()构造器通过jQuery.clean([match[1]], context);语句实现把HTML片断生成DOM元素,jQuery.clean()是一个公共函数。源代码及其注释如下所示。

jQuery.clean()包含三个参数,其中elems和context可以支持多种形式的值。Elems参数可以为数组、类数组、对象结构的形式。数组元素和对象属性可以混合使用。

对于数字类型参数,则会被转换为字符串型,除了字符串型外,其他的都放入返回的数组中,当然对于集合形式只需要读取集合中每个元素即可。

对于字符串型参数,则把它转换成DOM元素,再存入返回的数组中。转换的方式是,把HTML字符串片段赋值给创建的div元素的innerHTML,这样就可以把HTML字符串片段挂到DOM文档树中,从而实现把字符串转换成DOM元素。

在转换过程中,应该考虑HTML语法约定,因为标签嵌套是有严格限制的,例如,<td>必须存在<tr>中。因此在执行转换前,还应该对HTML字符串进行预处理,即修正HTML标签不规范的用法,这也是jQuery.clean()函数的一个重要工作。

广州网站建设,网站建设,广州网页设计,广州网站设计
  1. //公共函数扩展  
  2. jQuery.extend({  
  3.     //把HTML字符串片段转换成DOM元素  
  4.     //参数说明:  
  5.     //elems参数表示多个HTML字符串片段的数组  
  6.     // context参数表示上下文  
  7.     // fragment参数表示框架对象  
  8.     clean: function( elems, context, fragment ) {  
  9.         contextcontext = context || document;    //默认的上下文是document  
  10.          //在IE中!context.createElement是错误用法,因为它返回的是对象类型,而不是逻辑值,故通过返回类型进行判断  
  11.         if ( typeof context.createElement === "undefined" )  
  12.             //支持context为jQuery对象,并获取第一个元素  
  13.             contextcontext = context.ownerDocument ||  context[0] && context[0].ownerDocument || document;  
  14.         //如果近匹配一个标签,且没有指定框架参数,则直接创建DOM元素,并跳过后面的解析  
  15.         if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {  
  16.             var match = /^<(\w+)\s*\/?>$/.exec(elems[0]);  
  17.             if ( match )  
  18.                 return [ context.createElement( match[1] ) ];  
  19.         }  
  20.         var ret = [], scripts = [], div = context.createElement("div");  
  21.         //匹配每一个HTML字符串片段,并为每一个片段执行回调函数  
  22.         jQuery.each(elems, function(i, elem){  
  23.             if ( typeof elem === "number" )    //把数值转换为字符串的高效方法  
  24.                 elem += '';  
  25.             if ( !elem )    //如果不存在元素,则返回,或者为''、 undefined、false等时也返回  
  26.                 return;  
  27.             //把HTML字符串转换为DOM节点  
  28.             if ( typeof elem === "string" ) {  
  29.                 //统一转换为XHTML严谨型文档的标签形式,如<div/>的形式修改为<div></div> 
  30.                 //但是对于(abbr|br|col|img|input|link|meta|param|hr|area|embed)不修改      
  31.                 //front=(<(\w+)[^>]*?)  
  32.                 elemelem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){  
  33.                     return tag.match(/^(abbr|br|col|img|inpu t|link|meta|param|hr|area|embed)$/i) ?  
  34.                         all :  
  35.                         front + "></" + tag + ">";  
  36.                 });  
  37.                 // 清除空格,否则indexof可能会出现不能正常工作  
  38.                 var tags = elem.replace(/^\s+/, "").substring(0, 10).toLowerCase();  
  39.                 //有些标签必须是有一些约束的,如<option>必须在<select></select>中间  
  40.                 //下面代码大部分是对<table>中的子元素进行修正。数组中第一个元素为深度  
  41.                 var wrap =  
  42.                     //约束<option><opt在开始位置上(index=0)就返回&&运算符后面的数组  
  43.                     !tags.indexOf("<opt") &&  
  44.                     [ 1, "<select multiple='multiple'>", "</select>" ] ||  
  45.                     //<leg 必须在<fieldset>内部  
  46.                     !tags.indexOf("<leg") &&  
  47.                     [ 1, "<fieldset>", "</fieldset>" ] ||  
  48.                     //thead|tbody|tfoot|colg|cap必须在<table>内部  
  49.                     tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&  
  50.                     [ 1, "<table>", "</table>" ] ||  
  51.                     !tags.indexOf("<tr") &&  
  52.                     [ 2, "<table><tbody>", "</tbody></table>" ] ||  
  53.                      //<tr<tbody>中间  
  54.                      //td在tr中间  
  55.                      //col在<colgroup>中间  
  56.                     (!tags.indexOf("<td") || !tags.indexOf("<th")) &&  
  57.                     [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||  
  58.                     !tags.indexOf("<col") &&  
  59.                     [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||  
  60.                     // IE can't serialize <link> and <script> tags normally  
  61.                     !jQuery.support.htmlSerialize &&  
  62.                     //IE中 link script不能串行化  
  63.                     [ 1, "div<div>", "</div>" ] ||  
  64.                     //默认不修正  
  65.                     [ 0, "", "" ];  
  66.                 // 包裹HTML之后,采用innerHTML转换成DOM  
  67.                 div.innerHTML = wrap[1] + elem + wrap[2];  
  68.                 // 转到正确的深度,对于[1, "<table>","</table>"],div=<table> 
  69.                 while ( wrap[0]-- )  
  70.                     divdiv = div.lastChild;  
  71.                 // fragments去掉IE对<table>自动插入的<tbody> 
  72.                 if ( !jQuery.support.tbody ) {  
  73.                     //第一种情况:tags以<table>开头但没有<tbody>。在IE生成的元素中可能会自动加<tbody> 
  74.                     // 第二种情况:thead|tbody|tfoot|colg|cap为tags,那wrap[1] == "<table>"  
  75.                     var hasBody = /<tbody/i.test(elem),  
  76.                         tbody = !tags.indexOf("<table") && !hasBody ?  
  77.                             div.firstChild && div.firstChild.childNodes :  
  78.                         // tbody不一定是tbody,也有可能是thead等  
  79.                         wrap[1] == "<table>" && !hasBody ?  
  80.                             div.childNodes :  
  81.                             [];  
  82.                     //除去<tbody> 
  83.                     for ( var j = tbody.length - 1; j >= 0 ; --j )  
  84.                         if ( jQuery.nodeName( tbody[ j ], "tbody" )  && !tbody[ j ].childNodes.length )  
  85.                             tbody[ j ].parentNode.removeChild( tbody[ j ] );  
  86.                     }  
  87.                 //使用innerHTML,IE会去掉开头的空格节点,因此加上去掉的空格节点  
  88.                 if ( !jQuery.support.leadingWhitespace && /^\s/.test( elem ) )  
  89.                     div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );  
  90.                 //elem从字符转换成了数组  
  91.                 elem = jQuery.makeArray( div.childNodes );  
  92.             }  
  93.             //如果是DOM元素,则推入数组,否则就合并数组  
  94.             if ( elem.nodeType )  
  95.                 ret.push( elem );  
  96.             else  
  97.                 ret = jQuery.merge( ret, elem );  
  98.         });  
  99.         //如果指定了第3个参数,即框架对象,则附加到框架对象上  
  100.         //这段是新增加的,用来处理js代码,同时也取消了form的处理  
  101.         if ( fragment ) {  
  102.             for ( var i = 0; ret[i]; i++ ) {  
  103.                 if ( jQuery.nodeName( ret[i], "script" ) && (!ret[i].type  || ret[i].type.toLowerCase() === "text/javascript") ) {  
  104.                     scripts.push( ret[i].parentNode ? ret[i].parentNode. removeChild( ret[i] ) : ret[i] );  
  105.                 } else {  
  106.                     if ( ret[i].nodeType === 1 )  
  107.                         ret.splice.apply( ret, [i + 1, 0].concat (jQuery.makeArray(ret[i]. getElementsByTagName ("script"))) );  
  108.                     fragment.appendChild( ret[i] );  
  109.                 }  
  110.             }  
  111.             //返回脚本  
  112.             return scripts;  
  113.         }  
  114.         //返回DOM元素集合  
  115.         return ret;  
  116.     },  
  117. //……  

上面这段代码实际上最后访问的是一个名为ret的数组,数组中的元素变为DOM元素的对象,而它的innerHTML正好就是刚才的HTML字符串。

广州网站建设,网站建设,广州网页设计,广州网站设计

标签:
飞机