简要:当我们用$()时,便会直接调用zepto.init 生成zepto对象,那zepto.init是如何根据不同类型的参数来生产指定对象呢?

zepto.init = function(selector, context) {
var dom
// If nothing given, return an empty Zepto collection
//未传参,undefined进行boolean转换,返回空Zepto对象
// 如果$()未传入参数则走下面这句,如果传入一个参数则为selector,context为null,如果传入两个参数则都不为null
if (!selector) return zepto.Z()
// Optimize for string selectors //selector是字符串,即css表达式
/*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代码时
if (selector[0] == '<' && fragmentRE.test(selector))
//调用片段生成dom
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
//如果selector是函数,则在DOM ready的时候执行它
else if (isFunction(selector)) return $(document).ready(selector)
// If a Zepto collection is given, just return it
//如果selector是一个Zepto对象,返回它自己
else if (zepto.isZ(selector)) return selector
else {
// normalize array if an array of nodes is given
//如果selector是数组,过滤null,undefined
if (isArray(selector)) dom = compact(selector)
// Wrap DOM nodes.
//如果selector是对象,TODO://转换为数组? 它应是DOM; 注意DOM节点的typeof值也是object,所以在里面还要再进行一次判断
else if (isObject(selector))
dom = [selector], selector = null
// If it's a html fragment, create nodes from it
//如果selector是复杂的HTML代码,调用片段换成DOM节点
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
//如果存在上下文context,仍在上下文中查找selector
else if (context !== undefined) return $(context).find(selector)
// And last but no least, if it's a CSS selector, use it to select nodes.
// 如果没有给定上下文,在document中查找selector
else dom = zepto.qsa(document, selector)
}
// create a new Zepto collection from the nodes found
//将查询结果转换成Zepto对象
return zepto.Z(dom, selector)
}

1:这里首先判断如果没有传入参数,则返回新建的zepto对象

2:如果传入的是函数,$(function(){}) ,则执行$(document).ready(),即在文档加载完后执行自定义函数

3:如果selector本身就是一个zepto对象,则直接返回它自己

4:如果selector不是一个zepto对象,则根据不同类型的selector生产节点对象并赋值于dom

5:如果selector是数组,则将数组里的无效值去掉后赋值给dom

6:如果selector是对象

7:如果selector是html片段

8:如果selector是css选择字符串且context有值

9:如果selector是css选择字符串且context无值

10:调用zepto.Z,生产zepto对象

这里先看一下zepto.Z的内部实现:

//实际构造函数`
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 || ''
} zepto.Z = function(dom, selector) {
return new Z(dom, selector)
}

首先这里Z里面传入的dom参数要求是数组,如果dom为null或undefined则this.length = 0;this.selector = selector,并返回this;这里可以认为是this继承了dom

zepto.fragment: 将HTML转化为DOM

/**
* 内部函数 HTML 转换成 DOM
* 原理是 创建父元素,innerHTML转换
* @param html html片段
* @param name 容器标签名
* @param propertie 附加的属性对象
* @returns {*}
*/
zepto.fragment = function(html, name, properties) {
var dom, nodes, container // A special case optimization for a single tag
// 如果是单个元素,创建dom
// TODO
// RegExp 是javascript中的一个内置对象。为正则表达式。
  // RegExp.$1是RegExp的一个属性,指的是与正则表达式匹配的第一个 子匹配(以括号为标志)字符串,以此类推,RegExp.$2,RegExp.$3,..RegExp.$99总共可以有99个匹配
if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1)) if (!dom) {
//修正自闭合标签 如<div />,转换成<div></div>
if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
//给name取元素名
if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
//设置容器名,如果不是tr,tbody,thead,tfoot,td,th,则容器名为div
//为什么设置容器,是严格按照HTML语法,虽然tr td th浏览器会会自动添加tbody
if (!(name in containers)) name = '*'; container = containers[name] //创建容器
container.innerHTML = '' + html //生成DOMW
//取容器的子节点,TODO:子节点集会返回 $.each返回第一个参数
dom = $.each(slice.call(container.childNodes), function(){
container.removeChild(this) //把创建的子节点逐个删除
})
}
//如果properties是对象,遍历它,将它设置成DOM的属性
if (isPlainObject(properties)) {
//转换成Zepto Obj,方便调用Zepto的方法
nodes = $(dom)
//遍历对象,设置属性
$.each(properties, function(key, value) {
// 优先获取属性修正对象,通过修正对象读写值
// methodAttributes包含'val', 'css', 'html', 'text', 'data', 'width', 'height', 'offset',
// TODO: 奇怪的属性
if (methodAttributes.indexOf(key) > -1) nodes[key](value)
else nodes.attr(key, value)
})
} //返回dom数组 如[div,div]
return dom
}

这里涉及到几个正则表达式:

1:singleTagRE 匹配单个元素

var singleTagRE = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
var name = (singleTagRE.test("<p></p>")&&RegExp.$1);  //这里可以正常匹配<p>,<p/>,<p></p>
console.log(name); 结果:p

2: tagExpanderRE

var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
var html = "<div/>".replace(tagExpanderRE, "<$1></$2>");
console.log(html);
VM412:4 <div></div>
undefined
var tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
var html = "<input/>".replace(tagExpanderRE, "<$1></$2>");
console.log(html);
VM413:4 <input/>

3: fragmentRE:这里取出元素名 name 是为了判断是否为表格元素,为以后的container的选取做准备

var fragmentRE = /^\s*<(\w+|!)[^>]*>/;
var name = fragmentRE.test("<div></div>") && RegExp.$1;
console.log(name);
VM443:4 div
undefined
var fragmentRE = /^\s*<(\w+|!)[^>]*>/;
var name = fragmentRE.test("<input/>") && RegExp.$1;
console.log(name);
VM444:4 input
undefined
var fragmentRE = /^\s*<(\w+|!)[^>]*>/;
var name = fragmentRE.test("<div><input/></div>") && RegExp.$1;
console.log(name);
VM445:4 div
undefined
var fragmentRE = /^\s*<(\w+|!)[^>]*>/;
var name = fragmentRE.test("<div><input/>") && RegExp.$1;
console.log(name);
VM446:4 div
undefined
var fragmentRE = /^\s*<(\w+|!)[^>]*>/;
var name = fragmentRE.test("<div></div><input/>") && RegExp.$1;
console.log(name);
VM447:4 div

zepto源码研究 - zepto.js (zepto.init)的更多相关文章

  1. zepto源码研究 - deferred.js(jquery-deferred.js)

    简要:zepto的deferred.js 并不遵守promise/A+ 规范,而在jquery v3.0.0中的defer在一定程度上实现了promise/A+ ,因此本文主要研究jquery v3. ...

  2. zepto源码研究 - fx_methods.js

    简要:依赖fx.js,主要是针对show,hide,fadeIn,fadeOut的封装. 源码如下: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zept ...

  3. zepto源码研究 - fx.js

    简要:zepto 提供了一个基础方法animate来方便我们运用css动画.主要针对transform,animate以及普通属性(例如left,right,height,width等等)的trans ...

  4. zepto源码研究 - ajax.js($.ajax具体流程分析)

    简要:$.ajax是zepto发送请求的核心方法,$.get,$.post,$.jsonp都是封装了$.ajax方法.$.ajax将jsonp与异步请求的代码格式统一起来,内部主要是先处理url,数据 ...

  5. zepto源码研究 - ajax.js($.ajaxJSONP 的分析)

    简要:jsonp是一种服务器和客户端信息传递方式,一般是利用script元素赋值src来发起请求.一般凡是带有src属性的元素发起的请求都是可以跨域的. 那么jsonp是如何获取服务器的数据的呢? j ...

  6. zepto源码研究 - callback.js

    简要:$.Callbacks是一个生成回调管家Callback的工厂,Callback提供一系列方法来管理一个回调列表($.Callbacks的一个私有变量list),包括添加回调函数, 删除回调函数 ...

  7. zepto源码研究 - ajax.js(请求过程中的各个事件分析)

    简要:ajax请求具有能够触发各类事件的功能,包括:触发全局事件,请求发送前事件,请求开始事件,请求结束事件等等,贯穿整个ajax请求过程,这是非常有用的,我们可以利用这些事件来做一些非常有意思的事情 ...

  8. zepto源码研究 - zepto.js - 1

    简要:网上已经有很多人已经将zepto的源码研究得很细致了,但我还是想写下zepto源码系列,将别人的东西和自己的想法写下来以加深印象也是自娱自乐,文章中可能有许多错误,望有人不吝指出,烦请赐教. 首 ...

  9. 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二八║ Nuxt 基础:面向源码研究Nuxt.js

    前言 哈喽大家周五好,又是一个开开心心的周五了,接下来就是三天小团圆啦,这里先祝大家节日快乐咯,希望都没有加班哈哈,今天公司发了月饼,嗯~时间来不及了,上周应该搞个活动抽中几个粉丝发月饼的,下次吧,这 ...

随机推荐

  1. CSS3自定义图标

    http://ntesmailfetc.blog.163.com/blog/static/206287061201292631536545/ http://www.zhihu.com/question ...

  2. Ultra UltraEdit中取消提示:你要转换 File 为 DOS 格式吗?

    Ultra Edit中取消提示:文件可能不是DOS格式,你要转换 File 为 DOS 格式吗? UE 提示 取消取消这个提示: 高级 -> 配置 -> 文件处理 -> DOS/UN ...

  3. VC++大数据量绘图时无闪烁刷屏技术实现(我的理解是,在内存上作画,然后手动显示,而不再直接需要经过WM_PAINT来处理了)

    http://hantayi.blog.51cto.com/1100843/383578 引言 当我们需要在用户区显示一些图形时,先把图形在客户区画上,虽然已经画好但此时我们还无法看到,还要通过 程序 ...

  4. linux crontab 计划任务 atd和windows下的计划任务

    crontab 命令 如果发现您的系统里没有这个命令,请安装下面两个软件包. vixie-cron crontabs crontab 是用来让使用者在固定时间或固定间隔执行程序之用,换句话说,也就是类 ...

  5. android开发--翻转闹铃(从制作到打包)

    (转载请声明,文章原作地址http://blog.csdn.net/buptgshengod) 最近在家放假,一直想做一个手机应用,于是就自己动手做起来了.想到一个注意就是当闹铃响的时候翻转闹铃,声音 ...

  6. 开源src镜像

    开源src镜像: http://download.savannah.gnu.org/releases/

  7. POJ2251 Dungeon Master(bfs)

    题目链接. 题目大意: 三维迷宫,搜索从s到e的最小步骤数. 分析: #include <iostream> #include <cstdio> #include <cs ...

  8. 【转】byte[]数组比较(内容比较)--不错

    原文网址:http://amanda.blog.51cto.com/7238262/1215118 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责 ...

  9. 【转】掌握java枚举类型(enum type)

    原文网址:http://iaiai.iteye.com/blog/1843553 1   背景 在java语言中还没有引入枚举类型之前,表示枚举类型的常用模式是声明一组具有int常量.之前我们通常利用 ...

  10. dos 下 注册win 组件 ocx 后缀的

    C:\WINDOWS\system32>regsvr32 NTGraph.ocx