读zepto核心源码学习JS笔记(3)--zepto.init()

zepto.init()

1. 首先是第一种情况,selector为空

既然是反向分析,那我们先看看这句话的代码;

`if (!selector) return zepto.Z()`

这里的返回值为zepto.Z();那我们继续往上找zepto.Z()函数
java zepto.Z = function(dom, selector) { return new Z(dom, selector) }
这个函数仍然拥有一个返回值,Z函数的实例,同样的道理,我们继续去找Z() ;
```java
function Z(dom, selector) {
var i, len = dom ? dom.length : 0
for (i = 0; i < len; i++) this[i] = dom[i]
this.length = len
this.selector = selector || ''
}
根据以上代码可以分析出,当没有参数时,会得到一个length:0,selector:''的对象.

QQ截图20170608110900.png

2. 当selector为字符串的时候,又分为三种情况;

同样的,我们先看看这句话的代码
```java
else if (typeof selector == 'string') {
    selector = selector.trim()
}
```
  • 第一种,当selector为html片段

    if (selector[0] == '<' && fragmentRE.test(selector))
          dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    
    • (1) fragmentRE.test(selector)

      这里的fragmentRE是Zepto函数在之前定义的一段正则;

      //<div>erfwef</div>  取出<div>
      fragmentRE = /^\s*<(\w+|!)[^>]*>/,
      
    • (2) zepto.fragment(selector, RegExp.$1, context)

      • RegExp.$1
        RegExp.$1为RegExp的一个属性,指的是与正则表达式匹配的第一个 子匹配(以括号为标志)字符串;
        例子:
          var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
          r.exec('1985-10-15');
          s1=RegExp.$1;
          s2=RegExp.$2;
          s3=RegExp.$3;
          alert(s1+" "+s2+" "+s3)//结果为1985 10 15
      
      • zepto.fragment()函数
      //对应上面的代码,这里第一个参数是selector,就是我们在写代码时的$('xxx')中的xxx,
      //name为RegExp.$1,即正则匹配的第一个()里的东西,就是标签元素,例如 div p  h1等
      zepto.fragment = function(html, name, properties) {
            var dom, nodes, container
            // singleTagRE仍为之前定义的变量
            //singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, 匹配值如下截图
            //如html传入值为<p></p>,匹配singleTagRE,则创建<p></p>,并调用$('<p></p>')
            if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))
            //如果不匹配
            if (!dom) {
              //这是一段修复代码,将<div/>之类的不正常的代码修复成<div></div>;
              //具体的下面再讲解
              if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
              //如果没有标签名,,给他一个标签,fragmentRE = /^\s*<(\w+|!)[^>]*>/,
              if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
              //containers = {tr': document.createElement('tbody'),tbody': table, 'thead': table, 'tfoot': table,td': tableRow, 'th': tableRow,'*': document.createElement('div')},
              //如果name值不在container范围内,则标签名为div
              if (!(name in containers)) name = '*'
              //创建容器
              container = containers[name]
              //把html片段放入到容器中
              container.innerHTML = '' + html
              //这里调用了$.each();一会再详细讲解,这里是涉及到哪个函数我就去解析哪个函数
              //emptyArray = [], slice = emptyArray.slice,
              //所以这里的slice.call即为Array.prototype.slice.call(),能将具有length属性的对象转成数组;
              dom = $.each(slice.call(container.childNodes), function(){
              //删除
                container.removeChild(this)
              })
            }
            //如果properties为对象
            if (isPlainObject(properties)) {
            //$(dom)将dom转化成zepto对象;是为了方便调用其他方法;
              nodes = $(dom)
              $.each(properties, function(key, value) {
              //methodAttributes = ['val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset'],
              //如果设置的key在methodAttributes内,则直接调用zepto上的方法;
                if (methodAttributes.indexOf(key) > -1) nodes[key](value)
                else nodes.attr(key, value)
              })
            }
            //<p><span></span></p>返回[p,span]
            return dom
      }
      
      • singleTagRE
        QQ截图20170608135118.png
      • tagExpanderRE


        QQ截图20170608142535.png
      • fragmentR
        QQ截图20170608173421.png
  • 第二种 当context有值

     else if (context !== undefined) return $(context).find(selector)
    

    这里涉及到一个方法find,是$.fn中的方法,之后做统一分析;

  • 第三种 没有context;

     else dom = zepto.qsa(document, selector)
    
      zepto.qsa = function(element, selector){
          var found,
          //判断是不是ID
          maybeID = selector[0] == '#',
          //判断是不是css
          maybeClass = !maybeID && selector[0] == '.',
          //看是不是class和id名,如果是,将'#'或者'.'去除,然后赋值给nameOnlt;
          //否则,直接将值赋值;
          nameOnly = maybeID || maybeClass ? selector.slice(1) : selector,
          //simpleSelectorRE = /^[\w-]*$/,
          //匹配字母数字下划线和减号的组合;
          isSimple = simpleSelectorRE.test(nameOnly)
          //如果有内置getElementById方法,并且是id名;
      return (element.getElementById && isSimple && maybeID) ?
          //则返回element.getElementByID(nameOnly)
        ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :
        //反之的话,再做一次判断
        //若element不为元素节点,document,DocumentFragment时;为空,
        (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :
        //否则,将节点转换成数组;
        slice.call(
        //这里是一个三元运算符里套着另一个三元运算符;
          isSimple && !maybeID && element.getElementsByClassName ?
          //当为class,则调用element.getElementsByClassName(nameOnly) 
                maybeClass ? element.getElementsByClassName(nameOnly) :
                  //否则调用tagName;
                element.getElementsByTagName(selector) :
         //这个否则是最外层的判断;
            element.querySelectorAll(selector)
        )
    }
    

3. 当传入的值为函数时,则在dom加载后执行它;

else if (isFunction(selector)) return $(document).ready(selector)

4. 如果selector为Z的实例对象.则返回他自己;

else if (zepto.isZ(selector)) return selector

5. 最后,又分为5种情况;

  • 如果selector为数组;

    //
    if (isArray(selector)) dom = compact(selector)
    

    这里用到了一个compact方法;

    //这里调用了一个filter方法,是在$.fn内,以后统一分析;
    //这个函数是去除数组中的null和undefined;
    function compact(array) { return filter.call(array, function(item){ return item != null }) }
    

    所以当为数组的时候,去除数组中的null和undefined;

  • selector为对象

    else if (isObject(selector))
        dom = [selector], selector = null
    

    如果selector为对象,将对象变为一个数组;

  • selector为html片段;则将其转换成dom

    else if (fragmentRE.test(selector))
        dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    
  • 有context的时候

    else if (context !== undefined) return $(context).find(selector)
    
  • 没有context

    else dom = zepto.qsa(document, selector)
    
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容