在公司一直做移动端的项目,偶尔会做点PC端的东西,但基本上都是和移动端打交道。

移动端嘛必须上zepto,简单介绍下Zepto:它是一个面向高级浏览器的JavaScript框架的,实现JQuery的大部分API,尤其针对手机上web开发(流量金贵,JQ又太重了,体积太大,考虑太多性能不好),因此选择Zepto.js一个非常不错的选择!纵观各大网站选用zepto的特别多。

做移动端为了让页面更轻巧,大多都是自己写原生代码,遇到一些问题,我一般都是去看zepto的实现,把其中的一些实现搬到自己代码中,久而久之、对zepto就熟悉了。自己一直看可是从来没做过笔记,写写文章,相当于做笔记。

进入正题:zepto官网 地址  学习的版本是目前最新版 v1.1.6

再上一张图,一个大神画的,不是我画的。

这张图基本上包含了zepto的api,并且进行了分类整理。

在该github上下载zepto的源码也是进行模块划分的

在官网上下载的zepto默认导入了其中五个个模块,如果用到其他模块需要自己手动导入,这个事情我一般用grunt搞定。

从github上下载下来的代码可以看到有很多个文件,其中的核心文件就是zepto.js

先从这个文件入手,看下这个文件903行,声明了一个全局变量Zepto,照理说Zepto已经挂载到window上了,这里为什么还window.Zepto = Zepto再次进行赋值,不解!

window.$ === undefined && (window.$ = Zepto)

windwo上的$对象没有被占用就直接赋值为Zepto,我们平时使用$(XXX)的时候也可以替换成Zepto(XXX),但是没有必要,多写四个字符不累啊!

var Zepto=(function(){XXXX})();

Zepto后面是一个立即执行函数,内部肯定返回了某个对象然后赋值给Zepto

所以我展开立即执行函数,反倒最下面看到以下代码

    //把$.fn赋值给Z.prototype、zepto.Z.prototype
zepto.Z.prototype = Z.prototype = $.fn // Export internal API functions in the `$.zepto` namespace
zepto.uniq = uniq
zepto.deserializeValue = deserializeValue
$.zepto = zepto
//返回内部的$对象
return $

其他的代码先不管什么意思,反正这里返回了$对象,那么我们平时使用的全局$其实就是内部的$,最后看下内部哪里声明的$这个东西

    $ = function(selector, context) {
return zepto.init(selector, context)
}

发现内部的$其实就是一个函数,内部是return zepto.init(selector, context)

我们平时写的$(XXX) 其实就是调用的zepto.init(XX)

再次回到原点,平时我们都是怎么使用$, 都有哪些用法? JQuery的$好像有八九用法

1. jQuery([selector,[context]])
2. jQuery(element)
3. jQuery(elementArray)
4. jQuery(object)
5. jQuery(jQuery object)
6. jQuery(html,[ownerDocument])
7. jQuery(html,[attributes])
8. jQuery()
9. jQuery(callback)

总结下也就几种

1、$(selector,context?) 传入一个选择器返回一个zepto对象

2、$(function(){}) 传入一个函数,dom ready时执行

3、$(html,attrs?) 传入一个html字符串,构建元素,返回一个或zepto对象

4、$(dom obj)传入dom对象返回zepto对象

以上操作最后都是调用zepto.init(selector, context),我们的重点就是分析zepto.init这个函数

    zepto.init = function(selector, context) {
var dom
// If nothing given, return an empty Zepto collection
// 如果啥都没传直接返回一个空的Zepto集合
if (!selector) return zepto.Z()
// Optimize for string selectors
// 如果第一个参数是string
else if (typeof selector == 'string') {
//去掉空格
selector = selector.trim()
// If it's a html fragment, create nodes from it
// Note: In both Chrome 21 and Firefox 15, DOM error 12
// is thrown if the fragment doesn't begin with <
// 如果是一个HTML片段,创建节点注意,在chrome21和FF15版本,
// DOM错误12不是以<被抛出
if (selector[0] == '<' && fragmentRE.test(selector))
dom = zepto.fragment(selector, RegExp.$1, context), selector = null
// If there's a context, create a collection on that context first, and select
// nodes from there
//如果存在一个上下文环境,在这个上下文对象中去选择节点
else if (context !== undefined) return $(context).find(selector)
// If it's a CSS selector, use it to select nodes.
// 如果是一个css选择器,用它来选择节点
else dom = zepto.qsa(document, selector)
}
// If a function is given, call it when the DOM is ready
// 如果一个函数存在,在domready就绪后触发
else if (isFunction(selector)) return $(document).ready(selector)
// If a Zepto collection is given, just return it
// 如果zepto已经收集给出,直接返回
else if (zepto.isZ(selector)) return selector
else {
// normalize array if an array of nodes is given
// 如果节点已经为数组,进行聚合
if (isArray(selector)) dom = compact(selector)
// Wrap DOM nodes.
// 包装DOM节点
else if (isObject(selector))
dom = [selector], selector = null
// If it's a html fragment, create nodes from it
// 如果是一个HTML片段,对该片段创建节点
else if (fragmentRE.test(selector))
dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null
// If there's a context, create a collection on that context first, and select
// nodes from there
else if (context !== undefined) return $(context).find(selector)
// And last but no least, if it's a CSS selector, use it to select nodes.
else dom = zepto.qsa(document, selector)
}
// create a new Zepto collection from the nodes found
// 对发现的节点创建一个新的Zepto集合,这里把查询到dom 对象和selector 传递给了zepto.Z
return zepto.Z(dom, selector)
}

里面有6个return,即是六中情况

1、return zepto.Z(),返回一个空的zepto对象:

2、return $(context).find(selector)

3、return $(document).ready(selector)

4、if (zepto.isZ(selector)) return selector

5、return $(context).find(selector)

6、return zepto.Z(dom, selector)

观察发现除了第三和第五两种情况会真正返回,其他情况最终都会去构建一个zepto对象,最后都会走到:zepto.Z(dom, selector) 这个方法

zepto.Z = function(dom, selector) {
return new Z(dom, selector)
}

其实相当于一个工厂方法,在这里new了一个Z,外面每次我们调用$(XX)拿到的都是新的实例对象,但是我们并没有new,其实就是这里帮我们new了,JQuery也这样,这种思想到处都有用到。

最后我们还得参看Z的实现,这里和老版有所不同

    function Z(dom, selector) {
var i, len = dom ? dom.length : 0
//把dom对象数组放到this上,所以我们外部可以XX[0]得到一个原生的dom对象,关键就在这里,this是一个伪数组
for (i = 0; i < len; i++) this[i] = dom[i]
//把长度赋给this.length
this.length = len
//这个就不说了
this.selector = selector || ''
}

直接返回了一个Z的实例对象。先看一个demo

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test zepto</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-cacle=1.0,maximum-scale=1.0">
<meta content="telephone=no" name="format-detection">
<meta content="email=no" name="format-detection">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<style> </style>
</head>
<body>
<h1 id='test'>test</h1>
<ul id='items'>
<li>List item 1 <span class='delete'>DELETE</span></li>
<li>List item 2 <span class='delete'>DELETE</span></li>
</ul>
<div id='block'></div>
<script type="text/javascript" src="../zepto-full-1.1.6.js"></script>
<script>
var s=$('#items');
console.log(s)
</script>
</body>
</html>

这个demo 我们得到的test1对象如下

按之前的分析Z对象有length ;  Z[0]、Z[1]…… 伪数组;  还有selector

但是现在Z的原型__proto__指向了zepto.z[0]这个对象;所以返回的对象我们可以test1.attr()、test1.addClass()、test1.after()访问这些方法,是因为这个实例对象的原型能够访问到这些方法。那么问题来了,Z的原型什么时候指向zepto.z[0],zepto.z[0]是神马东西

带着这个疑问,继续查看源码,发下如下代码

    //把$.fn赋值给Z.prototype、zepto.Z.prototype
zepto.Z.prototype = Z.prototype = $.fn
// Export internal API functions in the `$.zepto` namespace
zepto.uniq = uniq
zepto.deserializeValue = deserializeValue
$.zepto = zepto
//返回内部的$对象
return $
$.fn下的所有方法都挂在了zepto.Z的prototype和Z.prototype下,也就是说上面的test1已经拥有了$.fn的所有方法。$.fn上的方法也就是$的实例方法,$上还有一大堆静态方法,不用创建一个$对象也可以调用。
我使用的版本是1.1.6,以前的版本 在这里实现略有不同,但是大同小异,搞懂了原型、原型链、继承这些都不是问题。 细心的话会发现一个问题,test的__proto__ 指向的是zepto.z[0], 试问问为什么会是zepto.z[0]这个东西,感觉怪怪的。
为什么会是zepto.z[0]、zepto.z[0]是什么东西,下回分解!!

zepto源码学习-01-整体感知的更多相关文章

  1. 【iScroll源码学习01】准备阶段 - 叶小钗

    [iScroll源码学习01]准备阶段 - 叶小钗 时间 2013-12-29 18:41:00 博客园-原创精华区 原文  http://www.cnblogs.com/yexiaochai/p/3 ...

  2. spring源码学习——spring整体架构和设计理念

    Spring是在Rod Johnson的<Expert One-On-One J2EE Development and Design >的基础上衍生而来的.主要目的是通过使用基本的java ...

  3. ibatis源码学习1_整体设计和核心流程

    背景介绍ibatis实现之前,先来看一段jdbc代码: Class.forName("com.mysql.jdbc.Driver"); String url = "jdb ...

  4. Mybatis源码学习之整体架构(一)

    简述 关于ORM的定义,我们引用了一下百度百科给出的定义,总体来说ORM就是提供给开发人员API,方便操作关系型数据库的,封装了对数据库操作的过程,同时提供对象与数据之间的映射功能,解放了开发人员对访 ...

  5. zepto源码学习-05 ajax

    学习zeptoajax之前需要先脑补下,强烈推荐此文http://www.cnblogs.com/heyuquan/archive/2013/05/13/js-jquery-ajax.html 还有A ...

  6. 【requireJS源码学习01】了解整个requireJS的结构

    前言 现在工作中基本离不开requireJS这种模块管理工具了,之前一直在用,但是对其原理不甚熟悉,整两天我们来试着学习其源码,而后在探寻其背后的AMD思想吧 于是今天的目标是熟悉requireJS整 ...

  7. 【iScroll源码学习01】准备阶段

    前言 我们昨天初步了解了为什么会出现iScroll:[SPA]移动站点APP化研究之上中下页面的iScroll化(上),然后简单的写了一个demo来模拟iScroll,其中了解到了以下知识点: ① v ...

  8. zepto源码学习-06 touch

    先上菜,看这个模块的最后一段代码,一看就明白. ['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown', 'doubleTap', 't ...

  9. jQuery 源码学习 - 01 - 简洁的 $('...')

    首先贴上学习参考资料:[深入浅出jQuery]源码浅析--整体架构,备用地址:chokcoco/jQuery-. jQuery 库,js 开发的一个里程碑,它的出现,让网页开发者们告别荒蛮的上古时代, ...

随机推荐

  1. 虚拟机Linux系统中安装SYNOPSYS工具图解教程

                                        V TRON KO 2.8.2 启动 dv 在终端运行命令: lmli2 然后再运行命令: dv V TRON KO V TRO ...

  2. js动态生成按钮,页面用DIV简单布局2

    对前边不完善的修改 <!DOCTYPE html><html><head><title>test.html</title> <meta ...

  3. 论js中的prototype

    今天在阅读代码时,碰到了prototype //判断是否是数组function isArray(obj) { return Object.prototype.toString.call(obj) == ...

  4. JAXB - XML Schema Types, Defining an Enumeration

    If you want a data type that enumerates discrete values you should use a restriction of the schema t ...

  5. 以 280W 数据为依据。对比SQL2008 表分区前和分区后的 T_SQL 效率

    一: 数据库的优化一直项目后期的重中之重,特别是当单表数据庞大到1000W时候.各种SQL语句执行效率都会慢很多.SQL 效率 与索引,行数据,列数据,以及Where 刷选字段类型 (效率 整数型大于 ...

  6. Android之 Fragment

    什么是Fragment: Android是在Android 3.0 (API level 11)开始引入Fragment的. 可以把Fragment想成Activity中的模块,这个模块有自己的布局, ...

  7. Android基础之Activity

    一.什么是Activity Activity是Android四大组件之一,并且Activity是组件中的重中之重. Activity是为用户提供一个用于信息交互的窗口. 二.如何去创建Activity ...

  8. hanoi双塔

    汉诺塔,经典的递归. 经典的汉诺塔游戏相信很多同学都会玩的,规则就不用赘述,百科一下就OK.有三个柱子A,B,C,A柱子上套有n个大小不等的盘子,任意两个盘子,上面的盘子一定小于下面的盘子.现在请你编 ...

  9. MFC下拉框使用方法

    Combo Box (组合框)控件很简单,可以节省空间.从用户角度来看,这个控件是由一个文本输入控件和一个下拉菜单组成的.用户可以从一个预先定义的列表里选择一个选项,同时也可以直接在文本框里面输入文本 ...

  10. 第3条:用私有构造器或者枚举类型强化Singleton属性

    Singleton是指仅仅被实例化一次的类.通过被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统. 在http://www.cnblogs.com/13jhzeng/p/5256424. ...