zoukankan      html  css  js  c++  java
  • jQuery源码学习(2):选择器初窥

    选择器初窥

    代码架构:

    jQuery选择器可以依照传入数据的类型分为五大类:

    • 传入字符串:$("div"), $("#id"), $(".div1"),$(".div p.title")
    • 传入html代码:$("<div></div>"), $("<div>1</div><div>2</div>")
    • 传入对象:$(document), $(this)
    • 传入数组或对象字面量:$({}), $([])
    • 传入函数:$(function(){})

    下面我们来看一下jQuery构造函数代码(jQuery-2.2.2第2832行起)的架构:

    jQuery.fn.init = function(selector, context){
      if(!selector){
    
        // part1.处理$(null), $(undefined), $(false), $("")
    
      }
      if(typeof selector == "string"){   
    
        // part2.匹配selector并将结果传入match中 
    
      }
        if(match && (match[1] || !context)){
    
          // part3.创建标签或按#id查询
    
    
        }else{
    
          // part4.处理复杂选择器
    
        }
      }
      // 一些其他的不常见情况
      else {...}
      return jQuery.makeArray(selector, this);
    }

    可以发现jQ将代码依照selector的类型分为了几个部分。下面我们来依次分析这几部分的代码。

    第一部分:检测没有传入值的情况

    此段完整代码如下:

    // HANDLE: $(""), $(null), $(undefined), $(false)
    if ( !selector ) {
      return this;
    }

    第二部分:匹配传入的字符串

    此段完整代码如下:

    if ( selector[ 0 ] === "<" &&selector[ 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 );
    }
    // 匹配html标签或#id
    rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/,

    通过分析rquickExpr正则表达式,我们可以得出在selector分别为以下几种值时返回值match的结构:

    1. selector = "<div>"

    match = [null, "<div>", null]

    2. selector = "<div>content</div>"

    match = [null, "<div>content</div>", null]

    3. selector = "<div></div>content"

    match = ["<div></div>content", "<div></div>", null]

    4. selector = #id

    match = [#id, null, #id]

    第三部分:创建标签或者按#id查询

    传入标签时:

    此段完整代码如下:

    // 如果是html标签
      if ( match[ 1 ] ) {
    // 如果传入的context是jQ对象,将其转换成原生对象
        context = context instanceof jQuery ? context[0] : context;
    
    // 将传入的html字符串转换成节点数组并传入this中
        jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true));
    
    // 如果是$(html, props)的形式,则要设置对应属性或执行方法
        if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
          for (match in context) {
    
    // 若 prop 的某一项是jQ方法
            if (jQuery.isFunction(this[match])) {
              this[match](context[match]);
    
    // 否则设置对应属性
            } else {
              this.attr(match, context[match]);
            }
          }
        }
    
        return this;
      }
    // 匹配单标签
    var rsingleTag = ( /^<([w-]+)s*/?>(?:</1>|)$/ );

    关键位置的语意都已在注释中讲解过了,下面主要介绍一下$.parseHTML和$.merge这两个方法在其中的应用:

    jQuery.parseHTML( data [, context ] [, keepScripts ] )
    • data:需要被转换成节点的字符串
    • context:被转换的节点所存在的上下文。并没有太大用处,默认是document,在需要在iframe中进行操作时,也可以设成contentWindow。
    • keepScripts:布尔值。设置成true时允许将字符串中的<script>部分也转换成节点。
    jQuery.merge(first, second)

    我们经常用$.merge来进行数组的合并。在本例中需要强调的一点是,$.merge被用来将一个数组合并到类数组对象中。就像下面这样:

      var obj = {0: "hello", 1: "pansy", length: 2};
      var arr = ["from", "arr"];
    
      console.log($.merge(obj, arr));   // Object {0: "hello", 1: "pansy", 2: "from", 3: "arr", length: 4}

    传入id时:

    // HANDLE: $(#id)
    else {
      elem = document.getElementById( match[ 2 ] );
    
      // Support: Blackberry 4.6
      // gEBID returns nodes no longer in the document (#6963)
      if ( elem && elem.parentNode ) {
    
        // Inject the element directly into the jQuery object
        this.length = 1;
        this[ 0 ] = elem;
      }
    
      this.context = document;
      this.selector = selector;
      return this;
    }

    第四部分:处理复杂选择器

    // 处理形如$(".class"), $("ul li+p")等等
    if ( !context || context.jquery ) {
      return ( context || root ).find( selector );
    
    // 当传入上下文是原生对象时,调用构造函数返回jQ对象
    } else {
      return this.constructor( context ).find( selector );
    }

    此处复杂选择器全部借助$().find()方法实现,使用了sizzle引擎,我们稍后再进行介绍。

  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/timl525/p/5335149.html
Copyright © 2011-2022 走看看