Zepto.js之一步步看源码(一)

最近博主再看zepto.js的源码,zepto.js相较起来比较简短,适合第一次读源码,主要是怕以后忘记,就写下笔记来记录这次源码之旅,总体来说收获还是挺大的。zepto.js就类似于一个迷你的jquery,直接来就仔细来看看这源码怎么回事,我用的版本是Zepto v1.1.6

首先我们看下总体结构

var Zepto = (function() {
    return $
})()

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

这里是一个自执行函数的返回值赋值给了Zepto,在下面给window下面的Zepto赋值,我们就可以通过Zepto(“#id”)这样来调用,之后的也是赋值给了window下的$,这也是我们最常见的$("#id"),这个表达式是如何计算的呢,当前面是真的时候就返回后面的语句,如果不明白建议看看&&的用法。

我们已经知道总体是怎么回事,那么我们就看看自执行函数里面返回的$是什么

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

这里可以看出这个$返回了一个初始化函数,这个初始化函数主要的左右是来判断$("")这里面到底是什么样式,根据不同的样式来分配给不同的方法处理

  zepto.init = function(selector, context) {
    var dom
   //如果是空的话就返回,一会再看zepto.Z()这个函数,其实就是绑定了原型链。
    if (!selector) return zepto.Z()
    else if (typeof selector == 'string') {
     //两种情况$("<p></p>")和$("#id")
      selector = selector.trim()
      // fragmentRE = /^\s*<(\w+|!)[^>]*>/,下面这个就是第一种创建元素的情况
      //这个正则表达式的意思是开头匹配(0,)个回车空格等符号下一个字符是<的之后有有{1,}个字母或数字,或者是!,之后有{0,}个>结尾,这个正则只能匹配出创建元素的情况,但不足以验证其内容的正确性,之后在方法里有验证其内容的正则表达式。zepto.fragment是来验证其内容的。因为很明显<2></2>也符合验证
      if (selector[0] == '<' && fragmentRE.test(selector))
       //下面的方法是来确认表达式,在创建元素,以后再展开吧。这里RegExp.$1为第一个子匹配(表达式中括号的部分)例如<p></p>匹配的就是p这样在fragment中p就是最外层的dom否则默认为div
        dom = zepto.fragment(selector, RegExp.$1, context), selector = null

      // $("#id","li")
      else if (context !== undefined) return $(context).find(selector)
      // $("#id")等我们常用的就在这个方法里
      else dom = zepto.qsa(document, selector)
    }
   //最后都返回一个dom元素节点,是个数组类型的里面装有原型链方法,之后再说
    如果是$(function(){})这个样式的就直接调用ready
    else if (isFunction(selector)) return $(document).ready(selector)
    // 传入的参数本身就已经是 zepto 对象,则直接返回
    else if (zepto.isZ(selector)) return selector
    else {

      // compact函数:过滤掉为null的项
      if (isArray(selector)) dom = compact(selector)

      // 如果传入的是object,直接强制塞进一个数组
      else if (isObject(selector)) dom = [selector], selector = null  
      // fragmentRE = /^\s*<(\w+|!)[^>]*>/ 还是取出第一个标签跟上面的差不多
      else if (fragmentRE.test(selector))
        dom = zepto.fragment(selector.trim(), RegExp.$1, context), selector = null 
      else if (context !== undefined) return $(context).find(selector)
      else dom = zepto.qsa(document, selector)
    }
    return zepto.Z(dom, selector)
  }

刚才上面的是一次初始化,主要是对于不同的写法干了不同的事,最后返回zepto.Z,我们看看这个函数

zepto.Z = function(dom, selector) {
    dom = dom || []
    //用过原型链的人知道这个__proto__ ,其实在自执行方法返回$的最后还有一段代码 zepto.Z.prototype = $.fn ,这样就是dom.__proto__ = zepto.Z.prototype,就相当于是构造函数实现原型链继承了。虽然自己继承自己,但应该是这么理解的。
    dom.__proto__ = $.fn
    dom.selector = selector || ''
    return dom
  }

最后返回的节点的样子就是

这里写图片描述

,有着各种方法的数组节点,方法都在$.fn中,下次在说说里面的方法,里面方法的写法读起来也收获良多。这次主要说的就是$("")执行这段代码到底发生了什么,深深体会到了代码编写的路漫漫啊。

猜你喜欢

转载自blog.csdn.net/qq_26626113/article/details/73692018
今日推荐