zepto源码研究 - zepto.js-4(常用的工具)

$.each:

/**
   * 以集合每一个元素作为上下文,来执行回调函数
   * @param elements
   * @param callback
   * @returns {*}
   */
  $.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
  }

这里的elements可以是数组或者对象,如果是对象,则会将其原型里面的属性也遍历出来,最后返回elments本身,如果回调函数返回了false,则终止循环

remove:

/**
     * 删除元素集
     * 原理   parentNode.removeChild
     * @returns {*}
     */
    remove: function(){
      //遍历到其父元素   removeChild
      return this.each(function(){
        if (this.parentNode != null)
          this.parentNode.removeChild(this)
      })
    },

这里的重点是parentNode.removeChild(this); 如果是没有父节点的这里不会执行。

is:

//返回集合中的第1条记录是否与selector匹配
    is: function(selector){
      return this.length > 0 && zepto.matches(this[0], selector)
    }

例如$("#id").is(".hasClass"); 实际就是调用matches进行匹配

not: 

//排除集合里满足条件的记录,接收参数为:css选择器,function, dom ,nodeList
    not: function(selector){
      var nodes=[]
      //当selector为函数时,safari下的typeof nodeList也是function,所以这里需要再加一个判断selector.call !== undefined
      if (isFunction(selector) && selector.call !== undefined)
        this.each(function(idx){
          //注意这里收集的是selector.call(this,idx)返回结果为false的时候记录
          if (!selector.call(this,idx)) nodes.push(this)
        })
      else {
        //当selector为字符串的时候,对集合进行筛选,也就是筛选出集合中满足selector的记录
        var excludes = typeof selector == ‘string‘ ? this.filter(selector) :
            //当selector为nodeList时执行slice.call(selector),注意这里的isFunction(selector.item)是为了排除selector为数组的情况
            //当selector为css选择器,执行$(selector)
            (likeArray(selector) && isFunction(selector.item)) ? slice.call(selector) : $(selector);
        this.forEach(function(el){
          //筛选出不在excludes集合里的记录,达到排除的目的
          if (excludes.indexOf(el) < 0) nodes.push(el)
        })
      }
      return $(nodes)//由于上面得到的结果是数组,这里需要转成zepto对象,以便继承其它方法,实现链写
    },

这里首先判断selector是否为函数,如果是,则遍历执行函数,如果返回false,则push到数组中

如果css选择字符串则调用this.filter(seelctor),这里有个小技巧使得not和filter相互调用

如果是数组或对象,则直接返回$(他自己)

最后遍历this,只要不是在excludes里面的都是满足条件的

has:

/*
     接收node和string作为参数,给当前集合筛选出包含selector的集合
     isObject(selector)是判断参数是否是node,因为typeof node == ‘object‘
     当参数为node时,只需要判读当前记当里是否包含node节点即可
     当参数为string时,则在当前记录里查询selector,如果长度为0,则为false,filter函数就会过滤掉这条记录,否则保存该记录
     */
    has: function(selector){
      return this.filter(function(){
        return isObject(selector) ?
            $.contains(this, selector) :
            $(this).find(selector).size()
      })
    },

重点提示下:这里的this如果也满足selector,则最后返回的结果集里也会有this  

show:

 
/** * 获取元素的默认display属性 * 是为了兼容什么? * @param nodeName * @returns {*} */function defaultDisplay(nodeName) {  var element, display  if (!elementDisplay[nodeName]) {  //缓存里没有

    element = document.createElement(nodeName)    document.body.appendChild(element)    display = getComputedStyle(element, ‘‘).getPropertyValue("display")    element.parentNode.removeChild(element)

    // display == "none",设置成blaock,即隐藏-显示    display == "none" && (display = "block")

    elementDisplay[nodeName] = display //TODO:缓存元素的默认display属性,缓存干嘛?  }  return elementDisplay[nodeName]}

/**
     * 展示
     * @returns {*}
     */
    show: function(){
      return this.each(function(){
        //清除内联样式display="none"
        this.style.display == "none" && (this.style.display = ‘‘)
        //计算样式display为none时,重赋显示值
        if (getComputedStyle(this, ‘‘).getPropertyValue("display") == "none")
          this.style.display = defaultDisplay(this.nodeName)
        //defaultDisplay是获取元素默认display的方法
      })
    },

this.style.display = ‘ ‘是清除元素的style里面的display样式,恢复元素的默认样式。

getComputedStyle(dom)能获取dom的所有css样式,第二个参数可以不传

getComputedStyle(dom,":after")能获取dom的:after伪类的所有css样式(这里只谈移动端)

详情请看:http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/

如果清除了style里面的display属性还是无效的话,直接显式的给display赋默认值,defaultDisplay的内部实际是在document里面新添加一个元素,来获取默认值的。

css:

/**
     * 读写样式   写:内联样式  读:计算样式
     *   原理 读:elment[style]/getComputedStyle, 写 this.style.cssText 行内样式设值
     * @param property   String/Array/Fun
     * @param value
     * @returns {*}
     */
    css: function(property, value){
      //只有一个传参,读
      if (arguments.length < 2) {
        var computedStyle, element = this[0]
        if(!element) return
        //getComputedStyle是一个可以获取当前元素所有最终使用的CSS属性值。返回的是一个CSS样式声明对象([object CSSStyleDeclaration]),只读
        //读到计算样式
        computedStyle = getComputedStyle(element, ‘‘)
        //设置样式
        if (typeof property == ‘string‘)// 字符串
        //优先读行内样式,再读计算样式,行内样式级别最高? TODO:似乎有bug,如果设置了!important 呢
          return element.style[camelize(property)] || computedStyle.getPropertyValue(property)
        else if (isArray(property)) {     //数组
          var props = {}
          $.each(property, function(_, prop){     //遍历读取每一条样式,存入JSON,返回
            props[prop] = (element.style[camelize(prop)] || computedStyle.getPropertyValue(prop))
          })
          return props
        }
      }

      //如果是写
      var css = ‘‘
      if (type(property) == ‘string‘) {
        if (!value && value !== 0)  //null,undefined时,删掉样式
          this.each(function(){
            //删除        dasherize是将字符串转换成css属性(background-color格式)
            this.style.removeProperty(dasherize(property))
          })
        else
        //‘-’格式值 + px单位
          css = dasherize(property) + ":" + maybeAddPx(property, value)
      } else {
        for (key in property)     //是对象时
          if (!property[key] && property[key] !== 0)
          //当property[key]的值为null/undefined,删除属性
            this.each(function(){ this.style.removeProperty(dasherize(key)) })
          else
          //‘-’格式值 + px单位
            css += dasherize(key) + ‘:‘ + maybeAddPx(key, property[key]) + ‘;‘
      }

      //设值   //TODO:   this.style.cssText +=  未考虑去重了
      return this.each(function(){ this.style.cssText += ‘;‘ + css })
    },

判断只传了一个参数:arguments.length < 2 或者 1 in  arguments,

流程大致如下:

1:判断参数,如果是一个参数则为只读模式

1.2:如果property为字符串,则 直接获取元素的css属性值

1.3:如果property为数组,则this.each遍历数组,获取每个属性的value值并形成props对象返回

2:若有2个参数,为写模式

2.1:如果property为字符串,则style.cssText+= property:value(这里的处理没有去重,但本人测了一下,这并不影响页面的渲染)

2.2:如果property为对象,则循环遍历property

这里有几个函数要提一下:

camelize() 将带“—”的转为驼峰命名例如“background-color”转为“backgroundColor”,对象属性是必须驼峰命名的。

dasherize()  将“backgroundColor”转为“background-color”,内部实现是用正则表达式匹配

style.removeProperty  删除style中的某个属性

style.setProperty(property,value,priority)  设置style中的某个属性,priority可取“important” ,(不太明白为什么zepto不用这个方法,望高人指教)

maybeAddPx (property,value):根据property类型给value加上“px”后缀

html:


/** * 处理 arg为函数/值 * 为函数,返回函数返回值 * 为值,返回值 * @param context * @param arg * @param idx * @param payload * @returns {*} */function funcArg(context, arg, idx, payload) {  return isFunction(arg) ? arg.call(context, idx, payload) : arg}
/**
     * 读写元素HTML内容
     * 原理 通过innerHTML读内容,append()写内容
     * @param html
     * @returns {*|string|string|string|string|string}
     */
    html: function(html){
      return 0 in arguments ?
          this.each(function(idx){
            var originHtml = this.innerHTML   //记录原始的innerHTMl
            //如果参数html是字符串直接插入到记录中,
            //如果是函数,则将当前记录作为上下文,调用该函数,且传入该记录的索引和原始innerHTML作为参数
            $(this).empty().append( funcArg(this, html, idx, originHtml) )
          }) :
          (0 in this ? this[0].innerHTML : null)
    },

html():不传参数则获取元素的innerHTML,

html("<div></div>"):设置元素的innerHTML

html(function(){....}):可传入方法,返回值设置为元素的innerHTML

这里的funcArg的功能是判断html为函数则以this为上下文,以idx,originHtml为参数执行函数

text:

/**
     * 读写元素文本内容
     * 原理:  通过 textContent 读写文本
     * @param text
     * @returns {*}
     */
    text: function(text){
      return 0 in arguments ?
          this.each(function(idx){                               //传参遍历写入
            var newText = funcArg(this, text, idx, this.textContent)
            this.textContent = newText == null ? ‘‘ : ‘‘+newText
          }) :
          (0 in this ? this[0].textContent : null)   //未传参读
    },

  




				
时间: 2024-10-25 08:41:08

zepto源码研究 - zepto.js-4(常用的工具)的相关文章

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

简要:zepto的deferred.js 并不遵守promise/A+ 规范,而在jquery v3.0.0中的defer在一定程度上实现了promise/A+ ,因此本文主要研究jquery v3.0.0中的defer. 首先   在上源码前,本人觉得有必要认识一下promise/A+ 规范:https://segmentfault.com/a/1190000002452115 接下来上源码: define( [ "./core", "./var/slice",

zepto源码研究 - fx_methods.js

简要:依赖fx.js,主要是针对show,hide,fadeIn,fadeOut的封装. 源码如下: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely distributed under the MIT license. ;(function($, undefined){ var document = window.document, docElem = document.documentElement, or

zepto源码研究 - zepto.js - 6(模板方法)

width  height  模板方法   读写width/height ['width', 'height'].forEach(function(dimension){ //将width,hegiht转成Width,Height,用于document获取 var dimensionProperty = dimension.replace(/./, function(m){ return m[0].toUpperCase() }) $.fn[dimension] = function(value

zepto源码研究 - callback.js

简要:$.Callbacks是一个生成回调管家Callback的工厂,Callback提供一系列方法来管理一个回调列表($.Callbacks的一个私有变量list),包括添加回调函数, 删除回调函数等等...,话不多说看正文: var memory, // Last fire value (for non-forgettable lists) fired, // Flag to know if list was already fired //是否回调过 firing, // Flag to

读Zepto源码之操作DOM

这篇依然是跟 dom 相关的方法,侧重点是操作 dom 的方法. 读Zepto源码系列文章已经放到了github上,欢迎star: reading-zepto 源码版本 本文阅读的源码为 zepto1.2.0 .remove() remove: function() { return this.each(function() { if (this.parentNode != null) this.parentNode.removeChild(this) }) }, 删除当前集合中的元素. 如果父

zepto源码分析系列

如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Zepto源码分析-event模块 Zepto源码分析-ajax模块 Zepto源码分析-form模块 Zepto源码分析-deferred模块 Zepto源码分析-动画(fx fx_method)模块 内容一定要200字一定要200字内容一定要200字一定要200字内容一定要200字一定要200字内容

Zepto源码分析-event模块

源码注释 // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely distributed under the MIT license. ;(function($){ var _zid = 1, undefined, slice = Array.prototype.slice, isFunction = $.isFunction, isString = function(obj){ return typeof obj

zepto源码--几个判断函数--学习笔记

几个需要经常用到的类型判断: 自定义一个类似于typeof的函数,提供更多的类型判断. 如果传入的参数为null,则类型返回'null',基本上可以返回各种常用对象类型,如'function', 'array','regexp'--而不是统一返回object. 判断是否为函数类型: 判断是不是window对象: 判断是不是document对象: 判断是否为object对象: 判断是否为{}对象: 判断是否为类数组:arguments就属于类数组,或者$('div')这种,可以用下标读取,看起来像

Zepto源码分析-form模块

源码注释 // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely distributed under the MIT license. ;(function($){ /** * 序列表单内容为JSON数组 * 返回类似[{a1:1},{a2:2}]的数组 * @returns {Array} */ $.fn.serializeArray = function() { var name, type, result =