zepto源码解读(二)——zpeto.init()——

前面第一节我们大致阐述了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 }
时间: 02-17

zepto源码解读(二)——zpeto.init()——的相关文章

(转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

转自:http://www.baiyuxiong.com/?p=886 ----------------------------------------------------------------------- 上一篇go语言nsq源码解读-基本介绍  介绍了最基本的nsq环境搭建及使用.在最后使用时,我们用到了几个命令:nsqlookupd.nsqd.nsqadmin.curl及 nsq_to_file,并看到用curl命令写入的几个”hello world”被nsq_to_file命令保

tars framework 源码解读(二) libservant部分源码的简介

还是直接用官方原图解说 服务端:可以理解成对外公开的接口 被调用时候响应流程 的底层封装 (响应端) NetThread: 收发包,连接管理,多线程(可配置),采用epoll ET触发实现,支持tcp/udp: BindAdapter: 绑定端口类,用于管理Servant对应的绑定端口的信息操作: ServantHandle:业务线程类,根据对象名分派Servant的对象和接口调用: AdminServant: 管理端口的对象: ServantImp: 继承Servant的业务处理基类(Serv

YYModel 源码解读(二)之NSObject+YYModel.h (1)

本篇文章主要介绍 _YYModelPropertyMeta 前边的内容 首先先解释一下前边的辅助函数和枚举变量,在写一个功能的时候,这些辅助的东西可能不是一开始就能想出来的,应该是在后续的编码过程中 逐步添加的. #define force_inline __inline__ __attribute__((always_inline)) 这行代码用到了C语言的内联函数 内联函数: 是用inline修饰的函数,内联函数在代码层次看和普通的函数结构一样,却不具备函数的性质,内联函数不是在调用时发生控

swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?

date: 2018-8-01 14:22:17title: swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?description: 阅读 sowft 框架源码, 了解 sowft 启动阶段的那些事儿 小伙伴刚接触 swoft 的时候会感觉 压力有点大, 更直观的说法是 难. 开发组是不赞成 难 这个说法的, swoft 的代码都是 php 实现的, 而 php 又是 世界上最好的语言, swoft 的代码阅读起来是很轻松的. 之后开发组会用 系列源码 解读文章, 深入解析

QCustomplot使用分享(二) 源码解读

一.头文件概述 从这篇文章开始,我们将正式的进入到QCustomPlot的实践学习中来,首先我们先来学习下QCustomPlot的类图,如果下载了QCustomPlot源码的同学可以自己去QCustomPlot的目录下documentation/qcustomplot下寻找一个名字叫做index.html的文件,将其在浏览器中打开,也是可以找到这个库的类图.如图1所示,是组成一个QCustomPlot类图的可能组成形式. 一个图表(QCustomPlot):包含一个或者多个图层.一个或多个ite

Zepto源码分析之二~三个API

由于时间关系:本次只对这三个API($.camelCase.$.contains.$.each)方法进行分析 第一个方法变量转驼峰:$.camelCase('hello-world-welcome'); 源码: var camelize; /** * 字符串替换 * 使用replace第二个参数带回调 */ camelize = function(str) { return str.replace(/-+(.)?/g, function(match, chr) { return chr ? ch

Spark学习之路 (十六)SparkCore的源码解读(二)spark-submit提交脚本

讨论QQ:1586558083 目录 一.概述 二.源码解读 2.2 find-spark-home 2.3 spark-class 2.4 SparkSubmit 正文 回到顶部 一.概述 上一篇主要是介绍了spark启动的一些脚本,这篇主要分析一下Spark源码中提交任务脚本的处理逻辑,从spark-submit一步步深入进去看看任务提交的整体流程,首先看一下整体的流程概要图: 回到顶部 二.源码解读 2.1 spark-submit # -z是检查后面变量是否为空(空则真) shell可以

structs2源码解读(6)之解析package标签

structs2源码解读之解析package标签 上面讨论过,在创建Dispacher对象时,调用dispacher.init()方法完成初始化,在这个方法中先创建各种配置文件的解析器(ConfigurationProvider),然后循环遍历这些解析器的register()方法解析各个配置文件.  for (final ContainerProvider containerProvider : providers)         {             containerProvider

struct2源码解读(9)之处理Action请求

struct2源码解读之处理Action请求 我们前面讨论过了struct2的初始化,我们先来回顾下  public void init(FilterConfig filterConfig) throws ServletException {         InitOperations init = new InitOperations();         try {             FilterHostConfig config = new FilterHostConfig(fil