WEB开发网
开发学院网页设计JavaScript Jquery源码分析---构建Jquery的Dom元素 阅读

Jquery源码分析---构建Jquery的Dom元素

 2010-09-14 13:36:44 来源:WEB开发网   
核心提示:在jQuery.fn.init函数中,最终的结果是把Dom元素放到jQuery对象的集合,Jquery源码分析---构建Jquery的Dom元素,我们可以传入单个Dom元素或Dom元素集合直接把其存到jQuery对象的集合,但是如果第一个参数是string类型的话,对于其它的length === 0的,也根本就不要加入

在jQuery.fn.init函数中,最终的结果是把Dom元素放到jQuery对象的集合,我们可以传入单个Dom元素或Dom元素集合直接把其存到jQuery对象的集合。但是如果第一个参数是string类型的话,如#id就要把Dom文档树去查找。对于html的片断就得生成Dom元素。我们再进一步,传入的单个Dom元素或Dom元素集合参数又是从那里来的?我们可以通过Dom元素的直接或间接的查找元素的方式。

这一部分首先分析如何从html的片断就得生成Dom元素,然后分析jQuery是如何通过直接或间接的方式在在Dom树中找到dom元素,第三就是分析基于CSS1~CSS3的CSS selector。

3.1生成Dom元素

Init方法中通过jQuery.clean([match[1]], context);来实现把html片断转换成Dom元素,这是一个静态方法:

// 把html转换成Dom元素,elems多个html string 的数组
clean : function(elems, context) {
   var ret = [];
   context = context || document;//默认的上下文是document
   //在IE中!context.createElement行不通,因为它返回对象类型
   if (typeof context.createElement == 'undefined')
      //这里支持context为jQuery对象,取第一个元素。
    context = context.ownerDocument || context[0]
           && context[0].ownerDocument || document;
  
  jQuery.each(elems, function(i, elem) {
// 把int 转换成string的最高效的方法
    if (typeof elem == 'number')elem += '';
    if (!elem) return;// 为'',undefined,false等时返回
    if (typeof elem == "string") {// 转换html为Dom元素
    // 修正 "XHTML"-style 标签,对于如<div/>的形式修改为<div></div>
    //但是对于(abbr|br|col|img|input|link|meta|param|hr|area|embed)
//不修改 。front=(<(w+)[^>]*?)
elem = elem.replace(/(<(w+)[^>]*?)/>/g,        function(all, front, tag) {  return      tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)? all: front + "></" + tag+ ">";}  );
    // 去空格,否则indexof可能会出不能正常工作
    var tags = jQuery.trim(elem).toLowerCase(),
    div = context.createElement("div");//在上下文中创建了一个元素<div>
    // 有些标签必须是有一些约束的,比如<option>必须在<select></select>中间
    // 下面的代码在大部分是对<table>中子元素进行修正。数组中第一个元素为深度     var wrap =
//<opt在开始的位置上(index=0)就返回&&后面的数组,这是对<option>的约束
!tags.indexOf("<opt")&& [1, "<select
multiple='multiple'>","</select>"]
  //<leg 必须在<fieldset>内部
  || !tags.indexOf("<leg")&& [1, "<fieldset>", "</fieldset>"]
  //thead|tbody|tfoot|colg|cap必须在<table>内部
  || tags.match(/^<(thead|tbody|tfoot|colg|cap)/)
&& [1, "<table>", "</table>"]
   //<tr在<tbody>中间
  || !tags.indexOf("<tr")&& [2, "<table><tbody>", "</tbody></table>"]
   //td在tr中间
   (!tags.indexOf("<td") || !tags.indexOf("<th"))&& [3,
"<table><tbody><tr>","</tr></tbody></table>"]
   //col在<colgroup>中间
  || !tags.indexOf("<col")&& [2,
"<table><tbody></tbody><colgroup>","</colgroup></table>"]
   //IE中 link script不能串行化 ?
  || jQuery.browser.msie&& [1, "div<div>", "</div>"]
   //默认不修正
  || [0, "", ""];
  
  // 包裹html之后,采用innerHTML转换成Dom
  div.innerHTML = wrap[1] + elem + wrap[2];
  
  while (wrap[0]--)
  // 转到正确的深度,对于[1, "<table>","</table>"],div=<table>
    div = div.lastChild;
  
  // fragments去掉IE对<table>自动插入的<tbody>
  if (jQuery.browser.msie) {             
  // 第一种情况:tags以<table>开头但没有<tbody>。在IE中生成的元素中可能会自动
// 加的<tbody> 第二种情况:thead|tbody|tfoot|colg|cap为tags,
// 那wrap[1] == "<table>" .tbody不一定是tbody,也有可能是thead等等
  var tbody = !tags.indexOf("<table")&& tags.indexOf("<tbody") < 0
        ? div.firstChild&& div.firstChild.childNodes
        : wrap[1] == "<table>"&& tags.indexOf("<tbody") < 0
           ? div.childNodes: [];
  // 除去<tbody>
   for (var j = tbody.length - 1;j >= 0; --j)
     if (jQuery.nodeName(tbody[j],
"tbody")&&!tbody[j].childNodes.length)            tbody[j].parentNode.removeChild(tbody[j]);
  
  //使用innerHTML,IE会去开头的空格节点的,加上去掉的空格节点
   if (/^s/.test(elem))               div.insertBefore(context.createTextNode
(elem.match(/^s*/)[0]),div.firstChild);
  }
  elem = jQuery.makeArray(div.childNodes);//elem从字符转换成了数组
}
   //采用===0,因为form,select都有length属性。这里主要是为了form,select进
//行下面的if else 处理。对于其它的length === 0的,也根本就不要加入到ret中。
if (elem.length === 0&& (!jQuery.nodeName(elem, "form")
         && !jQuery.nodeName(elem, "select")))
           return;
  //不是(类)数组的形式的元素,或是form元素或是select元素(这两个可以看作类数组)
if (elem[0] == undefined|| jQuery.nodeName(elem, "form")|| elem.options)
    ret.push(elem);
else// 对于elems是array-like的集合
  ret = jQuery.merge(ret, elem);
});
  //上面的each中把有效的元素都加入到ret,现在只要返回就得到转换的Dom元素数组
return ret;
},

1 2 3 4 5 6  下一页

Tags:Jquery 源码 分析

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接