zoukankan      html  css  js  c++  java
  • zepto的构造器$

    在zepto中,通过$来构造对象

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

    由该函数,实际上,在调用$函数时相当于调用init方法,接下来看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
        else if (typeof selector == 'string') {
          //消除空格
          selector = selector.trim()
          //这里根据不同的情况返回dom
          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.
          else dom = zepto.qsa(document, selector)
        }
        // If a function is given, call it when the DOM is ready
        else if (isFunction(selector)) return $(document).ready(selector)
        // If a Zepto collection is given, just return it
        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.
          else if (isObject(selector))
            dom = [selector], selector = null
          // If it's a html fragment, create nodes from it
          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
        return zepto.Z(dom, selector)
      }; 

    先来看一下当传入的是一个html标签的字符串时的构造过程:

    if (selector[0] == '<' && fragmentRE.test(selector))
            dom = zepto.fragment(selector, RegExp.$1, context), selector = null
    fragmentRE = /^s*<(w+|!)[^>]*>/;

    fragmentRE是一个匹配普通标签<xxx>的表达式,关键是zepto.fragment()函数。

    该函数传入三个参数,在这里传入的分别是selector, RegExp.$1, context,RegExp.$1储存的是当前调用的正则表达式匹配的第一个子表达式。即当我们传入<span>时,其值为span,接下来可以看fragment函数。

    zepto.fragment = function(html, name, properties) {
        var dom, nodes, container
    
        // A special case optimization for a single tag
        //创建一个元素
        if (singleTagRE.test(html)) dom = $(document.createElement(RegExp.$1))
    
        if (!dom) {
          //将html转换为标签,$1$2表示的是匹配的第一个和第二个子表达式
          if (html.replace) html = html.replace(tagExpanderRE, "<$1></$2>")
    
          if (name === undefined) name = fragmentRE.test(html) && RegExp.$1
          //创建一个name元素  根据是否为表格元素对其进行下一步操作
          if (!(name in containers)) name = '*'
    
          container = containers[name]
          //将标签插入name元素
          container.innerHTML = '' + html
          //$.each函数最终返回传入的第一个数组参数
          dom = $.each(slice.call(container.childNodes), function(){
            container.removeChild(this)
          })
        }
        if (isPlainObject(properties)) {
          //将dom转成zepto对象
          nodes = $(dom)
          $.each(properties, function(key, value) {
            if (methodAttributes.indexOf(key) > -1) nodes[key](value)
            else nodes.attr(key, value)
          })
        }
        return dom
      }

    在这个函数中,有两个正规表达式,分别是tagExpanderRE和singleTagRE

    tagExpanderRE = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([w:]+)[^>]*)/>/ig;
    singleTagRE = /^<(w+)s*/?>(?:</1>|)$/

    singleTagRE匹配的是单个的<span></span>诸如此类的标签,而tagExpanderRE匹配的是自闭合标签,如<span/>,但不能是img之类,并将其转成<span><span/>;

    从函数中,如果匹配的是单个的html标签,则直接创建该标签并$实例化,将其转变为一个zepto对象,如果匹配的是另一种情况,即将dom转成一个存储这些节点的数组。

    然后就是最后一个条件判断了:

               

    if (isPlainObject(properties)) {
          //将dom转成zepto对象
          nodes = $(dom)
          $.each(properties, function(key, value) {
            if (methodAttributes.indexOf(key) > -1) nodes[key](value)
            else nodes.attr(key, value)
          })
        }

     先看一下isPlainObject函数,该函数判断是否为一个纯对象:

    function isPlainObject(obj) {
        return isObject(obj) && !isWindow(obj) && Object.getPrototypeOf(obj) == Object.prototype
      }    

     主要的判断在于Object.getPrototypeOf(obj) == Object.prototype;不同的参数调用getPrototypeOf(obj)返回的值不同:

    条件判断里的代码需要注意一点,即将dom转成zepto对象.使其能调用$的attr方法,attr函数留在后面。

    重新回到init函数,接下来的都是一些条件判断,其中有一个是选择器函数 即zepto.qsa

    zepto.qsa = function(element, selector){
        var found,
            maybeID = selector[0] == '#',
            maybeClass = !maybeID && selector[0] == '.',
            nameOnly = maybeID || maybeClass ? selector.slice(1) : selector, // Ensure that a 1 char tag name still gets checked
            isSimple = simpleSelectorRE.test(nameOnly)
            //条件判断
        return (element.getElementById && isSimple && maybeID) ? // Safari DocumentFragment doesn't have getElementById
          ( (found = element.getElementById(nameOnly)) ? [found] : [] ) :
          (element.nodeType !== 1 && element.nodeType !== 9 && element.nodeType !== 11) ? [] :
          slice.call(
            isSimple && !maybeID && element.getElementsByClassName ? // DocumentFragment doesn't have getElementsByClassName/TagName
              maybeClass ? element.getElementsByClassName(nameOnly) : // If it's simple, it could be a class
              element.getElementsByTagName(selector) : // Or a tag
              element.querySelectorAll(selector) // Or it's not simple, and we need to query all
          )
      }

    这个函数就是单纯的选择器函数,init函数最后返回的是zepto.z(dom,selector);

    zepto.Z = function(dom, selector) {
        return new Z(dom, selector)
      }
    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.prototype = Z.prototype = $.fn

    通过中间的构造函数Z,原型链接到$.fn方便调用其方法,最终返回结果对象。

  • 相关阅读:
    R语言:提取路径中的文件名字符串(basename函数)
    课程一(Neural Networks and Deep Learning),第三周(Shallow neural networks)—— 0、学习目标
    numpy.squeeze()的用法
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 4、Logistic Regression with a Neural Network mindset
    Python numpy 中 keepdims 的含义
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 3、Python Basics with numpy (optional)
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 2、编程作业常见问题与答案(Programming Assignment FAQ)
    课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 0、学习目标
    课程一(Neural Networks and Deep Learning),第一周(Introduction to Deep Learning)—— 0、学习目标
    windows系统numpy的下载与安装教程
  • 原文地址:https://www.cnblogs.com/Darlietoothpaste/p/6579886.html
Copyright © 2011-2022 走看看