189 8069 5689

[置顶]   jQuery乱谈(三)

昨天说到了jQuery()的实现,还差一处理HTML字符串的部分没有分析完,今天继续。 

创新互联长期为近1000家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为鄯善企业提供专业的成都做网站、成都网站设计、成都外贸网站建设鄯善网站改版等技术服务。拥有10多年丰富建站经验和众多成功案例,为您定制开发。

if ( typeof selector === "string" ) {    if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {        // Assume that strings that start and end with <> are HTML and skip the regex check                 match = [ null, selector, null ];             }else {                 match= rquickExpr.exec( selector );             }    // Match html or make sure no context is specified for #id             if ( match && (match[1] || !context) ) {        // HANDLE: $(html) -> $(array)                 if ( match[1] ) {                     context= context instanceof jQuery ? context[0] : context;                     doc= ( context && context.nodeType ? context.ownerDocument || context : document );            // scripts is true for back-compat                     selector = jQuery.parseHTML( match[1], doc, true );            if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {                this.attr.call( selector, context, true );                     }            return jQuery.merge( this, selector );        // HANDLE: $(#id)                 } else {                     elem= document.getElementById( match[2] );            // Check parentNode to catch when Blackberry 4.6 returns                     // nodes that are no longer in the document #6963                     if ( elem && elem.parentNode ) {                // Handle the case where IE and Opera return items                         // by name instead of ID                         if ( elem.id !== match[2] ) {                    return rootjQuery.find( selector );                         }                // Otherwise, we inject the element directly into the jQuery object                         this.length = 1;                this[0] = elem;                     }            this.context = document;            this.selector = selector;            return this;                 }    // HANDLE: $(expr, $(...))             } else if ( !context || context.jquery ) {        return ( context || rootjQuery ).find( selector );    // HANDLE: $(expr, context)             // (which is just equivalent to: $(context).find(expr)             } else {        return this.constructor( context ).find( selector );             }         }

 下面我们来一段一段分析:

if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {  // Assume that strings that start and end with <> are HTML and skip the regex check           match = [ null, selector, null ];   }else {         match= rquickExpr.exec( selector );   }

 selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3这一句用于判断selector字符串是否由"<"开始,">"结尾,而且selector字符串的长度不小于3.就是类似于:$('

My new text

')这样的情况。如果selector是html标签组成的话,直接match = [ null, selector, null ];而不用正则检查。否则的话需要match = rquickExpr.exec( selector );。rquickExpr变量是在前面定义的一个正则式字面量:rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/ 。这段正则式只是一种检查HTML字符串的简便方式,优先检测#id,防止XSS通过location.hash***,利用检查正则表达式HTML字符串还是元素ID字符串。match = rquickExpr.exec( selector )这一句把字符串中的匹配正则表达式的文本保存到match数组里。这里用到了我们前面提到的正则表达式quickExpr,match其实是一个数组,第0个元素是与正则表达式相匹配的文本,第1个元素是与正则表达式的第1个子表达式相匹配的文本(如果有的话),第2个元素是第2个子表达式相匹配的文本(如果有的话),第3个元素是第3个子表达式相匹配的文本(如果有的话),这里就是元素的ID,不包含#。

 注:XSS***请参看:http://baike.baidu.com/view/2161269.htm; exec()方法请参看:http://www.w3school.com.cn/js/jsref_exec_regexp.asp

后面的一部分我将以注释的形式解释:     

          /**

       * 正则表达式匹配到了内容,并且 match[1]不为空,或者context为空。

       * match[1]不为空的时候selector是HTML字符串,也就是你可以用$("xland")把对象包装成jQuery对象        

       * context为空的时候selector是页面元素ID

       */

     if ( match && (match[1] || !context) ) {        // 处理$(html) -> $(array),选择器为html字符串                 if ( match[1] ) {                     context= context instanceof jQuery ? context[0] : context; // 不好意思,这句话我也不理解
            /**
            * ownerDocument属性返回节点所属的根元素。下面的JS语句保证了上下文(作用域)为根节点
            *
*/ doc= ( context && context.nodeType ? context.ownerDocument || context : document );
           /**
            *jQuery.parseHTML方法接受三个参数 (data, context, scripts)。data表示HTML字符串;            
* context表示是作用域,默认是document,可选;scripts
* 是一个boolean值,如果是true的话,就会把HTML字符串里面的脚本也正确解析
            *
            */
           selector = jQuery.parseHTML( match[1], doc, true );            if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {                this.attr.call( selector, context, true );                     }            return jQuery.merge( this, selector );        // 选择器为ID,处理形如$("#first")                 } else {                     elem= document.getElementById( match[2] ); // match[2]得到ID的值如:first                     if ( elem && elem.parentNode ) {                         if ( elem.id !== match[2] ) {                    return rootjQuery.find( selector ); // 找到元素                         }                // 否则直接把元素插入到爆jquery对象                         this.length = 1;                this[0] = elem;                     }            this.context = document;            this.selector = selector;            return this;                 }    // 处理 形如 $("div .container")的表达式字符串             } else if ( !context || context.jquery ) {        return ( context || rootjQuery ).find( selector );    // 处理 形如 $("div .container",$('#asd'))的表达式字符串,
// 相当于$(context).find(expr) ,就是在context上下文中查找
       } else {
         return this.constructor( context ).find( selector );
      }

 jQuery核心函数分析完毕,感觉还是有很多不满意的地方,慢慢改正吧。

--------------------------------------------添加---------------------------------------------------

 jQuery核心函数里面涉及到了merge()、find()函数。我简单解释一下这俩货吧,先说merge():

 

merge: function( first, second ) {var l = second.length,             i= first.length,             j= 0; if ( typeof l === "number" ) {    for ( ; j < l; j++ ) {                 first[ i++ ] = second[ j ];             }          }else {    while ( second[j] !== undefined ) {                 first[ i++ ] = second[ j++ ];             }         }          first.length= i; return first;     }

 

 该方法用于合并两个jQuery对象(因为jQuery对象中有length属性)或者数组内容到第一个对象或数组。使用方法为:jQuery.merge( first, second )。其中first数组是用来合并的数组或jQuery对象,元素是从第二数组或jQuery对象加进来的;second数组或jQuery对象合并到第一,保持不变。内部代码比较简单,主要是判断提供的第二个参数是jQuery对象(因为jQuery对象中有length属性)还是数组。其中:

if ( typeof l === "number" ) {    for ( ; j < l; j++ ) {                 first[ i++ ] = second[ j ];             }          }

 当第二个参数的length属性是number类型时,直接循环遍历把第二个参数的每一项添加到第一个参数的后面。接着:

else {    while ( second[j] !== undefined ) {                 first[ i++ ] = second[ j++ ];             }         }

 当第二个参数的length属性不是number类型时,循环把第二个参数的每一项添加到第一个参数的后面,一直到第二个参数的一项为undefined,也就是没有定义时结束。

 

 find()方法代码如下:

find: function( selector ) {var i, l, length, n, r, ret,             self= this;         // 处理jQuery对象或DOM元素if ( typeof selector !== "string" ) {    return jQuery( selector ).filter(function() {        for ( i = 0, l = self.length; i < l; i++ ) {            if ( jQuery.contains( self[ i ], this ) ) {                return true;                     }                 }             });         }         // 把DOM元素集合加入到jQuery堆栈中         ret= this.pushStack( "", "find", selector );         //  处理选择器字符串,循环把选择的元素添加到堆栈for ( i = 0, l = this.length; i < l; i++ ) {             length= ret.length;             jQuery.find( selector,this[i], ret );     if ( i > 0 ) {        // Make sure that the results are unique                 for ( n = length; n < ret.length; n++ ) {            for ( r = 0; r < length; r++ ) {                if ( ret[r] === ret[n] ) {                             ret.splice(n--, 1);                    break;                         }                     }                 }             }         } return ret;     }

 该方法可以获得当前元素匹配集合中每个元素的后代,选择性筛选的选择器。使用方法如下:

[置顶]          jQuery乱谈(三)

 如果一个jQuery对象表示一个DOM元素的集合, .find()方法允许我们能够通过搜索DOM树中的这些元素的后代元素从匹配的元素构造一个新的jQuery象。find()children()方法是相似的,但后者只是旅行的DOM树向下一个层级(就是只查找子元素,而不是后代元素)。该方法选择性地接受同一类型选择表达,我们可以传递给$()函数。如果紧随兄弟匹配选择器,它在新建成的jQuery对象中留下;否则,它被排除在外。

 


网页标题:[置顶]   jQuery乱谈(三)
本文URL:http://cdxtjz.com/article/gpcccs.html

其他资讯