• zepto源码解读(二)——zpeto.init()函数——(1)结构整理


    前面第一节我们大致阐述了zepto的设计结构,看起来东西很多,但是化整为零就没那么繁杂了,一起来看一看,首先我们来看一看zepto源码中可以说是最关键的函数之一zepto.init()。

    我们之前说到了$这个api会导致函数zepto返回$这个接口,$呢,是一个函数:

    1   // `$` will be the base `Zepto` object. When calling this
    2   // function just call `$.zepto.init, which makes the implementation
    3   // details of selecting nodes and creating Zepto collections
    4   // patchable in plugins.
    5   $ = function(selector, context){
    6     return zepto.init(selector, context)
    7   }

    可以看到$函数会返回另一个名为zepto.init()的函数,并且将传入的参数响应传递进去。(这里之所以直接给$赋值而不是var $因为之前已经声明了变量$,所以变量$并不会污染全局)。

    那么我们接着来看一看zepto.init()是一个什么样的函数,从字面上看init是初始化的意思。代码如下:

     1 zepto.init = function(selector, context) {
     2     var dom
     3     // If nothing given, return an empty Zepto collection
     4     if (!selector) return zepto.Z()
     5     // Optimize for string selectors
     6     else if (typeof selector == 'string') {
     7       selector = selector.trim()
     8       // If it's a html fragment, create nodes from it
     9       // Note: In both Chrome 21 and Firefox 15, DOM error 12
    10       // is thrown if the fragment doesn't begin with <
    11       //如果是<开头 >结尾  基本的HTML代码时
    12       if (selector[0] == '<' && fragmentRE.test(selector))
    13       //调用片段生成dom
    14         dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    15       // If there's a context, create a collection on that context first, and select
    16       // nodes from there
    17       else if (context !== undefined) return $(context).find(selector)
    18       // If it's a CSS selector, use it to select nodes.
    19       //通过css表达式查找元素
    20       else dom = zepto.qsa(document, selector)
    21     }
    22     // If a function is given, call it when the DOM is ready
    23     else if (isFunction(selector)) return $(document).ready(selector)
    24     // If a Zepto collection is given, just return it
    25     else if (zepto.isZ(selector)) return selector
    26     else {
    27       // normalize array if an array of nodes is given
    28       if (isArray(selector)) dom = compact(selector)
    29       // Wrap DOM nodes.
    30       else if (isObject(selector))
    31         dom = [selector], selector = null
    32       // If it's a html fragment, create nodes from it
    33       else if (fragmentRE.test(selector))
    34         dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    35       // If there's a context, create a collection on that context first, and select
    36       // nodes from there
    37       else if (context !== undefined) return $(context).find(selector)
    38       // And last but no least, if it's a CSS selector, use it to select nodes.
    39       else dom = zepto.qsa(document, selector)
    40     }
    41     // create a new Zepto collection from the nodes found
    42     return zepto.Z(dom, selector)
    43   }

    看起来很复杂对不对,还是用化整为零的思路,我们一步一步分开来看。首先看一下它的结构,用了很多的if else来判断并且处理传入的参数。最终!return zepto.Z()这个函数,可想而知,这个init函数应该是处理参数并且传出两个参数给zepto.Z(),一个名为dom,一个名为selector。至于这个zepto.Z是什么我们先不管,我们来好好看看其中几十行的if...else..是做什么用的。


      · 无参数,即$()

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

      · selector参数是字符串,例如$('p') $('<div>') $('#content')

     1   else if (typeof selector == 'string') {
     2       selector = selector.trim()
     3       // If it's a html fragment, create nodes from it
     4       // Note: In both Chrome 21 and Firefox 15, DOM error 12
     5       // is thrown if the fragment doesn't begin with <
     6       //如果是<开头 >结尾  基本的HTML代码时
     7       if (selector[0] == '<' && fragmentRE.test(selector))
     8       //调用片段生成dom
     9         dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    10       // If there's a context, create a collection on that context first, and select
    11       // nodes from there
    12       else if (context !== undefined) return $(context).find(selector)
    13       // If it's a CSS selector, use it to select nodes.
    14       //通过css表达式查找元素
    15       else dom = zepto.qsa(document, selector)
    16     }

     首先用trim()函数处理selecor参数,清除参数中的空格。

      情况1:参数为<div>这种形式,即是一个html标签的,那么dom变量会被赋值为用这个标签创建的DOM对象,就像dom = document.createElement('div')差不多。其中涉及到了fragmentREzepto.fragment两个我们尚未了解的东东,此处不要深究,知道这段代码的意思即可。

      情况2,如果第二个参数有值,则先根据第二个参数生成zepto对象,(此处算是一个回调函数)然后再调用.find来获取,例如$('.item', '#content')这种用法。find()方法是zepto对象的一个函数。

      情况3,以上两种情况都不是,则调用zepto.qsa来获取数据,后来聊这个方法的具体实现。qsaquerySelectAll的缩写。

      · selector参数是函数,例如$(function(){...})

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

     用到了isFunction()来判断是否为函数以及ready()函数的使用

      · selector本身就是个zepto对象

    这种用法比较少,但是也不能避免,例如:

    1 var a = $('p');
    2 $(a);  // 这里传入的 a 本身就是个 zepto 对象了。

      · 其他情况

     1    else {
     2       // normalize array if an array of nodes is given
     3       if (isArray(selector)) dom = compact(selector)
     4       // Wrap DOM nodes.
     5       else if (isObject(selector))
     6         dom = [selector], selector = null
     7       // If it's a html fragment, create nodes from it
     8       else if (fragmentRE.test(selector))
     9         dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    10       // If there's a context, create a collection on that context first, and select
    11       // nodes from there
    12       else if (context !== undefined) return $(context).find(selector)
    13       // And last but no least, if it's a CSS selector, use it to select nodes.
    14       else dom = zepto.qsa(document, selector)
    15     }

    情况1:selector参数是数组,则通过一个compact()处理一下赋值给dom

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

    情况2:selector参数是DOM节点,则将它作为数组赋值给dom。

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

    剩余情况:类似于字符串的操作,只是在输入时没有加入'' "导致不是字符串的情况。

    1     else if (fragmentRE.test(selector))
    2         dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
    3       // If there's a context, create a collection on that context first, and select
    4       // nodes from there
    5       else if (context !== undefined) return $(context).find(selector)
    6       // And last but no least, if it's a CSS selector, use it to select nodes.
    7       else dom = zepto.qsa(document, selector)

    总结

    zepto.init函数算是zepto源码中比较复杂的一个函数,一开篇就遇到了个硬骨头。不过我们这里暂且先把那些分叉放在一边,先把大路疏通,然后在慢慢的去一个一个攻破那些分叉。

    接下来我们再把init函数的结构梳理一下。

     1 zepto.init = function(selector, context) {
     2     var dom
     3 
     4     // 分情况对dom赋值:
     5     // 1. selector 为空
     6     // 2. selector 是字符串,其中又分好几种情况
     7     // 3. selector 是函数
     8     // 4. 其他情况,例如 selector 是数组、对象等
     9 
    10     // create a new Zepto collection from the nodes found
    11     return zepto.Z(dom, selector)
    12 }
  • 相关阅读:
    Javascript DOM 编程艺术读书笔记16/03/25
    2014 Multi-University Contest 1.1 hdu4861 打表找规律
    汇编小记16/3/23
    汇编小记16/3/22
    hdoj 4940 强连通图
    Head FIRST HTML & CSS 16/03/17
    html&css一些有用的网站整理
    dosbox+debug 模拟dos
    汇编小记16/3/15
    解决windwos另存为,保存文件时无法选择“桌面”文件夹
  • 原文地址:https://www.cnblogs.com/coderzzp/p/6413221.html
Copyright © 2020-2023  润新知