zoukankan      html  css  js  c++  java
  • Zepto源码分析(一)核心代码分析

    Zepto源码分析(一)核心代码分析
    Zepto源码分析(二)奇淫技巧总结

    本文只分析核心的部分代码,并且在这部分代码有删减,但是不影响代码的正常运行。

    目录

    
    * 用闭包封装Zepto
    * 开始处理细节
    * 正式处理数据(获取选择器选择的DOM)
    * 正式处理数据(添加DOM到当前实例)
    * 在实例的原型链上添加方法
    * 支持插件扩展
    * 验收
    
    

    用闭包封装Zepto

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    开始处理细节

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // [新增] 初始化zepto变量为对象
      var zepto = {}
    
      // [新增] 添加初始化方法。当selector参数为空时,则交给zepto.Z()处理
      //        当selector为字符串时则把zepto.qsa(document, selector)的值存到dom变量
      //        并且交给zepto.Z(dom, selector)处理
      zepto.init = function(selector, context) {
        var dom
        if (!selector) return zepto.Z()
        else if (typeof selector == 'string') {
          dom = zepto.qsa(document, selector)
        }
        return zepto.Z(dom, selector)
      }
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    正式处理数据(获取选择器选择的DOM)

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // 初始化zepto变量为对象
      var zepto = {}
    
      //  添加初始化方法。当selector参数为空时,则交给zepto.Z()处理
      //  当selector为字符串时则把zepto.qsa(document, selector)的值存到dom变量
      //  并且交给zepto.Z(dom, selector)处理
      zepto.init = function(selector, context) {
        var dom
        if (!selector) return zepto.Z()
        else if (typeof selector == 'string') {
          dom = zepto.qsa(document, selector)
        }
        return zepto.Z(dom, selector)
      }
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // [新增] 使用querySelectorAll(selector)查询DOM
      zepto.qsa = function(element, selector){
        return selector ? element.querySelectorAll(selector) : []
      }
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    正式处理数据(添加DOM到当前实例)

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // 初始化zepto变量为对象
      var zepto = {}
    
      // [新增] 开始正式处理数据。当dom长度为0则不添加内容,
      //        否则逐个将dom逐个到当前实例
      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)
      }
    
      //  添加初始化方法。当selector参数为空时,则交给zepto.Z()处理
      //  当selector为字符串时则把zepto.qsa(document, selector)的值存到dom变量
      //  并且交给zepto.Z(dom, selector)处理
      zepto.init = function(selector, context) {
        var dom
        if (!selector) return zepto.Z()
        else if (typeof selector == 'string') {
          dom = zepto.qsa(document, selector)
        }
        return zepto.Z(dom, selector)
      }
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // 使用querySelectorAll(selector)查询DOM
      zepto.qsa = function(element, selector){
        return selector ? element.querySelectorAll(selector) : []
      }
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    在实例的原型链上添加方法

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // 初始化zepto变量为对象
      var zepto = {}, emptyArray = []
    
      // 开始正式处理数据。当dom长度为0则不添加内容,
      // 否则逐个将dom逐个到当前实例
      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)
      }
    
      //  添加初始化方法。当selector参数为空时,则交给zepto.Z()处理
      //  当selector为字符串时则把zepto.qsa(document, selector)的值存到dom变量
      //  并且交给zepto.Z(dom, selector)处理
      zepto.init = function(selector, context) {
        var dom
        if (!selector) return zepto.Z()
        else if (typeof selector == 'string') {
          dom = zepto.qsa(document, selector)
        }
        return zepto.Z(dom, selector)
      }
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // 使用querySelectorAll(selector)查询DOM
      zepto.qsa = function(element, selector){
        return selector ? element.querySelectorAll(selector) : []
      }
    
      // [新增] 定义each方法
      $.each = function(elements, callback){
        var i, key
        if (likeArray(elements)) {
          for (i = 0; i < elements.length; i++)
            if (callback.call(elements[i], i, elements[i]) === false) return elements
        } else {
          for (key in elements)
            if (callback.call(elements[key], key, elements[key]) === false) return elements
        }
    
        return elements
      }
    
      // [新增] 定义用于扩展在原型链上的方法
      $.fn = {
        constructor: zepto.Z,
        length: 0,
        each: function(callback){
          emptyArray.every.call(this, function(el, idx){
            return callback.call(el, idx, el) !== false
          })
          return this
        },
        empty: function(){
          return this.each(function(){ this.innerHTML = '' })
        },
        html: function(html){
          return 0 in arguments ?
            this.each(function(idx){
              var originHtml = this.innerHTML
              $(this).empty().append( funcArg(this, html, idx, originHtml) )
            }) :
            (0 in this ? this[0].innerHTML : null)
        },
        test : function(){
          return this.each(function(){
            console.log('测试链式调用')
            return this 
          })
        }
      }
    
      // [新增] 原型链指向$.fn
      zepto.Z.prototype = Z.prototype = $.fn
      // $.zepto指向zepto
      $.zepto = zepto
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    支持插件扩展

    
    // 对全局暴露Zepto变量
    var Zepto = (function() {
    
      // 初始化zepto变量为对象
      var zepto = {}, emptyArray = []
    
      // 开始正式处理数据。当dom长度为0则不添加内容,
      // 否则逐个将dom逐个到当前实例
      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)
      }
    
      //  添加初始化方法。当selector参数为空时,则交给zepto.Z()处理
      //  当selector为字符串时则把zepto.qsa(document, selector)的值存到dom变量
      //  并且交给zepto.Z(dom, selector)处理
      zepto.init = function(selector, context) {
        var dom
        if (!selector) return zepto.Z()
        else if (typeof selector == 'string') {
          dom = zepto.qsa(document, selector)
        }
        return zepto.Z(dom, selector)
      }
    
      // 定义$变量,并将具体细节交给zepto.init处理
      $ = function(selector, context){
        return zepto.init(selector, context)
      }
    
      // [新增] 插件扩展函数
      function extend(target, source, deep) {
        for (key in source)
          if (source[key] !== undefined) target[key] = source[key]
      }
    
      // [新增] 插件扩展函数
      $.extend = function(target){
        var deep, args = emptyArray.slice.call(arguments, 1)
        if (typeof target == 'boolean') {
          deep = target
          target = args.shift()
        }
        args.forEach(function(arg){ extend(target, arg, deep) })
        return target
      }
    
      // 使用querySelectorAll(selector)查询DOM
      zepto.qsa = function(element, selector){
        return selector ? element.querySelectorAll(selector) : []
      }
    
      // 定义each方法
      $.each = function(elements, callback){
        var i, key
        if (likeArray(elements)) {
          for (i = 0; i < elements.length; i++)
            if (callback.call(elements[i], i, elements[i]) === false) return elements
        } else {
          for (key in elements)
            if (callback.call(elements[key], key, elements[key]) === false) return elements
        }
    
        return elements
      }
    
      // 定义用于扩展在原型链上的方法
      $.fn = {
        constructor: zepto.Z,
        length: 0,
        each: function(callback){
          emptyArray.every.call(this, function(el, idx){
            return callback.call(el, idx, el) !== false
          })
          return this
        },
        empty: function(){
          return this.each(function(){ this.innerHTML = '' })
        },
        html: function(html){
          return 0 in arguments ?
            this.each(function(idx){
              var originHtml = this.innerHTML
              $(this).empty().append( funcArg(this, html, idx, originHtml) )
            }) :
            (0 in this ? this[0].innerHTML : null)
        },
        test : function(){
          return this.each(function(){
            console.log('测试链式调用')
            return this 
          })
        }
      }
    
      // 原型链指向$.fn
      zepto.Z.prototype = Z.prototype = $.fn
      // $.zepto指向zepto
      $.zepto = zepto
    
      // 返回变量
      return $
    })()
    
    // 把Zepto变量挂载在window
    window.Zepto = Zepto
    // 当$变量没有被占用的时候,为Zepto设置别名为$
    window.$ === undefined && (window.$ = Zepto)
    
    

    验收

    
    // 链式调用测试
    $('head').test().test()  // 测试链式调用
    测试链式调用
    {0: head, length: 1, selector: "head"}
    $('head').html()  // <meta charset="utf-8"><link rel="dns-prefetch" href...
    
    // 编写插件测试
    ;(function($){
      $.extend($.fn, {
        bw2: function() {
          return this.html()
        }
      })
    })(Zepto)
    $('head').bw2()  // <meta charset="utf-8"><link rel="dns-prefetch" href...
    
    

    欢迎关注前端进阶指南微信公众号:

    fe

    另外我也创了一个对应的QQ群:660112451,欢迎一起交流。

  • 相关阅读:
    [原][osg]Geometry详解
    [osg]节点遍历nodevisitor浅析
    [原][osg]osgconv浅析
    [原][游戏][攻略]仙之侠道玖章-- --从入门到放弃
    [转][linux]简单的linux下的tcp/udp
    [转][c++][跨平台]c++跨平台开发小结
    人机交互,来和我猜拳吧!
    从零开始学测试【1】测试方法术语总结
    从零开始学测试【2】网页登录界面
    JSP 和 ASP.NET 谁能主宰未来【转】
  • 原文地址:https://www.cnblogs.com/bergwhite/p/7430946.html
Copyright © 2011-2022 走看看