一个普通的 Zepto 源码分析(一) - ie 与 form 模块

普通的路人,普通地瞧。分析时使用的是目前最新 1.2.0 版本。

Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以及 event 、 ajax 、 form ,还有一个说是可以支持 IE10 和 WP8 的 ie 模块。

Zepto 基本模块之 ie 模块

由于这个模块比较短小,就是一个对 getComputedStyle() 的封装,而且核心模块也有用到这个函数。那么首先来看看:

;(function(){
// getComputedStyle shouldn't freak out when called
// without a valid element as argument
try {
getComputedStyle(undefined)
} catch(e) {
var nativeGetComputedStyle = getComputedStyle
window.getComputedStyle = function(element, pseudoElement){
try {
return nativeGetComputedStyle(element, pseudoElement)
} catch(e) {
return null
}
}
}
})()

那么我们可以看到,这个模块对原生的 getComputedStyle() 做了一层封装,来屏蔽当传入参数不正确时抛出的异常。比如传入的第一个参数不是一个 Element 节点(继承自 Node 节点接口),而是其他的比如 document 或者是 Text 节点等,都会抛出异常。这里为了插件的正常运行,返回 null 就好了。

其他关于该函数的返回值、 CSS 安全等内容参见 MDN 。

Zepto 基本模块之 form 模块

另一个比较短小的模块,在原型上增加了 serialize()serializeArray()submit() 这 3 个方法。

serializeArray() 会把 form 表单序列化成一个由 namevalue 属性组成的对象的数组。

序列化函数 serialize()

没错,还是先看代码短的:

  $.fn.serialize = function(){
var result = []
this.serializeArray().forEach(function(elm){
result.push(encodeURIComponent(elm.name) + '=' + encodeURIComponent(elm.value))
})
return result.join('&')
}

嗯,非常的简单粗暴,直接把 this.serializeArray() 的结果遍历一遍来进一步序列化成 URL-encoded 的形式,不仅用了两倍空间,还用了两倍时间。至于 encodeURIComponent() 就是很常见的函数了,在 MDN 上有一个对该函数遵循 RFC3986 或 RFC5987 的修补实现。

我认为其实可以抽象出一个基本的遍历函数出来,再在两个序列化函数中传不同的参数或者回调函数来获得不同的输出。

另外,这里没有处理 POST 的数据格式,即把 %20 替换为 + ,我认为 Zepto 这个是错误的实现。所以翻了下 jQuery 的实现,果然(另 Zepto 的 $.param() 有这样的替换,见 ajax 模块):

    serialize: function() {
return jQuery.param( this.serializeArray() );
}

序列化成键值对象数组 serializeArray()

再看看长得丑的:

  $.fn.serializeArray = function() {
var name, type, result = [],
add = function(value) {
// 关注点 3 (可遍历元素的重入)
if (value.forEach) return value.forEach(add)
result.push({ name: name, value: value })
}
// 关注点 1
if (this[0]) $.each(this[0].elements, function(_, field){
type = field.type, name = field.name
// 关注点 2 (过滤无关的表单元素)
if (name && field.nodeName.toLowerCase() != 'fieldset' &&
!field.disabled && type != 'submit' && type != 'reset' && type != 'button' && type != 'file' &&
((type != 'radio' && type != 'checkbox') || field.checked))
add($(field).val())
})
return result
}

首先是拿到类数组集合对象的第一个元素,这里我猜如果通过 Zepto 查询到多个表单的话,最终序列化的也是第一个。

然后是对元素遍历,注意是 HTML form 元素有 elements 属性,若是一个其他元素比如 div 就直接返回空数组了。感觉可以做个存在判断,这样就不用进入函数了,但多一次判断的开销。

遍历回调中,使用了下划线屏蔽第一个参数,接着筛掉不需序列化的元素。这里把单选和多选也筛了,后面再检查 checked 属性,并不是因为有 option 元素(它是包含在 select 里的),而是像 button 把 type 设置一下就能成为单选或多选,或者其他一些自定义支持 checked 属性的元素的情况。

再看回前面的匿名函数表达式,赋值给了 add 并捕获了 nametypeadd 变量,当传入的值拥有 forEach 就会在其回调中重新调用自己,比如 select 下的值。否则就直接生成一个键值对象压入数组。

提交函数 submit()

最后看看同样代码比较短的:

  $.fn.submit = function(callback) {
// 关注点 1
if (0 in arguments) this.bind('submit', callback)
else if (this.length) {
var event = $.Event('submit')
this.eq(0).trigger(event)
// 关注点 2
if (!event.isDefaultPrevented()) this.get(0).submit()
}
return this
}

这里 0 in arguments 的判断应该是为速度做的优化,判断 in 还是比较快的。至于 bind() 也是常用的事件函数了(但已废弃)。如果没有传入回调函数,则使用 Event 插件在第一个表单上触发一个默认冒泡的 submit 事件,如果事件没有被阻止则调用 HTML 表单的 submit() ,注意区分 eq()get() ,后者是返回 HTML 元素的。

系列相关

一个普通的 Zepto 源码分析(一) - ie 与 form 模块

一个普通的 Zepto 源码分析(二) - ajax 模块

一个普通的 Zepto 源码分析(三) - event 模块

本文基于 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 发布,欢迎引用、转载或演绎,但是必须保留本文的署名 BlackStorm 以及本文链接 http://www.cnblogs.com/BlackStorm/p/Zepto-Analysing-For-IE-And-Form-Module.html ,且未经许可不能用于商业目的。如有疑问或授权协商请 与我联系

一个普通的 Zepto 源码分析(一) - ie 与 form 模块的更多相关文章

  1. 一个普通的 Zepto 源码分析(二) - ajax 模块

    一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...

  2. 一个普通的 Zepto 源码分析(三) - event 模块

    一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...

  3. Zepto源码分析(一)核心代码分析

    本文只分析核心的部分代码,并且在这部分代码有删减,但是不影响代码的正常运行. 目录 * 用闭包封装Zepto * 开始处理细节 * 正式处理数据(获取选择器选择的DOM) * 正式处理数据(添加DOM ...

  4. Zepto源码分析(二)奇淫技巧总结

    Zepto源码分析(一)核心代码分析 Zepto源码分析(二)奇淫技巧总结 目录 * 前言 * 短路操作符 * 参数重载(参数个数重载) * 参数重载(参数类型重载) * CSS操作 * 获取属性值的 ...

  5. zepto源码分析系列

    如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Ze ...

  6. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  7. jQuery 源码分析(二十一) DOM操作模块 删除元素 详解

    本节说一下DOM操作模块里的删除元素模块,该模块用于删除DOM里的某个节点,也可以理解为将该节点从DOM树中卸载掉,如果该节点有绑定事件,我们可以选择保留或删除这些事件,删除元素的接口有如下三个: e ...

  8. jQuery 源码分析(二十) DOM操作模块 插入元素 详解

    jQuery的DOM操作模块封装了DOM模型的insertBefore().appendChild().removeChild().cloneNode().replaceChild()等原生方法.分为 ...

  9. jQuery 源码分析(十二) 数据操作模块 html特性 详解

    jQuery的属性操作模块总共有4个部分,本篇说一下第1个部分:HTML特性部分,html特性部分是对原生方法getAttribute()和setAttribute()的封装,用于修改DOM元素的特性 ...

随机推荐

  1. 【Android Developers Training】 67. 响应触摸事件

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. spring auto-config

    spring security auto-config auto-config配置 <http auto-config="true"> </http> 自动 ...

  3. maven配置本地仓库(从本地仓库下载jar包到.m2仓库)

     Windows-->preference               把你的settings.xml存到一个地方maven指向你的settings.xmlsettings.xml里的地址是你们 ...

  4. java中方法的定义

    所谓的方法(将方法称为函数)指的就是一段可以被重复调用的代码块. 对于方法的返回值类型有两种使用形式: · 有数据返回:返回值类型就使用 Java 中定义的数据类型: · 无数据返回:使用 void ...

  5. .net 类型转换

    在.net  平台下类型有两种方式可以进行类型转换,强转或as转换.(有的说法是两种方式都进行强转,有两种强转方式). 如:typeA objA = (typeA)objB 或者使用另一种typeA ...

  6. spring+springmvc+mybaties整合实例

    spring+springmvc+mybaties即SSM框架整合在ecpliseee中开发:很么多西都是只有只有自己上手做,才会懂.昨晚熬了很久,才弄出来.也希望对新手有帮助!下面整理一下思路:关键 ...

  7. SVN分支/合并操作小记

    一.前言 说来惭愧,鄙人从事开发多年,使用svn已经好几个年头了,但是却仅限于update.commit.compare之类的操作,最近想到github上学习别人写的NIO源码,顺便去熟悉git的使用 ...

  8. js校验身份证

    1 <%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> &l ...

  9. foreach是怎么实现遍历的

    using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...

  10. LeetCode题解 343.Integer Break

    题目:Given a positive integer n, break it into the sum of at least two positive integers and maximize ...