一个普通的 Zepto 源码分析(一) - ie 与 form 模块
一个普通的 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 表单序列化成一个由 name 和 value 属性组成的对象的数组。
序列化函数 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 并捕获了 name 、 type 、 add 变量,当传入的值拥有 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 模块的更多相关文章
- 一个普通的 Zepto 源码分析(二) - ajax 模块
一个普通的 Zepto 源码分析(二) - ajax 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块,以 ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- Zepto源码分析(一)核心代码分析
本文只分析核心的部分代码,并且在这部分代码有删减,但是不影响代码的正常运行. 目录 * 用闭包封装Zepto * 开始处理细节 * 正式处理数据(获取选择器选择的DOM) * 正式处理数据(添加DOM ...
- Zepto源码分析(二)奇淫技巧总结
Zepto源码分析(一)核心代码分析 Zepto源码分析(二)奇淫技巧总结 目录 * 前言 * 短路操作符 * 参数重载(参数个数重载) * 参数重载(参数类型重载) * CSS操作 * 获取属性值的 ...
- zepto源码分析系列
如果你也开发移动端web,如果你也用zepto,应该值得你看看.有问题请留言. Zepto源码分析-架构 Zepto源码分析-zepto(DOM)模块 Zepto源码分析-callbacks模块 Ze ...
- jQuery 源码分析(十九) DOM遍历模块详解
jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...
- jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
本节说一下DOM操作模块里的删除元素模块,该模块用于删除DOM里的某个节点,也可以理解为将该节点从DOM树中卸载掉,如果该节点有绑定事件,我们可以选择保留或删除这些事件,删除元素的接口有如下三个: e ...
- jQuery 源码分析(二十) DOM操作模块 插入元素 详解
jQuery的DOM操作模块封装了DOM模型的insertBefore().appendChild().removeChild().cloneNode().replaceChild()等原生方法.分为 ...
- jQuery 源码分析(十二) 数据操作模块 html特性 详解
jQuery的属性操作模块总共有4个部分,本篇说一下第1个部分:HTML特性部分,html特性部分是对原生方法getAttribute()和setAttribute()的封装,用于修改DOM元素的特性 ...
随机推荐
- HTML5 Web SQL 数据库操作
Web SQL 数据库 API 并不是 HTML5 规范的一部分,但是它是一个独立的规范,引入了一组使用 SQL 操作客户端数据库的 APIs. 以下是规范中定义的三个核心方法: openDataba ...
- 排序算法总结及Java实现
1. 整体介绍 分类 排序大的分类可以分为两种,内排序和外排序.在排序过程中,全部记录存放在内存,则称为内排序,如果排序过程中需要使用外存,则称为外排序.主要需要理解的都是内排序算法: 内排序可以分为 ...
- pouchdb-all-dbs插件
pouchdb-all-dbs插件 用来获取所有数据库的名字列表 https://github.com/nolanlawson/pouchdb-all-dbs 使用方法 1.引入js文件(顺序如下) ...
- gulp实用配置(2)——中小项目
上一篇的gulp配置很简单,主要就是为了demo的查看和调试,这一篇则会相对详细一些,包括压缩合并打时间戳等. 在互联网环境比较好的城市,需要多人协作的,大一点的项目应该都用上了模块化(这里主要指co ...
- Kintinuous 相关论文 Volume Fusion 详解
近几个月研读了不少RGBD-SLAM的相关论文,Whelan的Volume Fusion系列文章的效果确实不错,而且开源代码Kintinuous结构清晰,易于编译和运行,故把一些学习时自己的理解和经验 ...
- MySQL存储写入性能严重抖动分析
案例描述: 通过iostat发现存储的写性能长期维持在10MB左右,而且因为写性能差已经导致数据库性能变差: 两个小时以后,iostat发现系统的写性能已经能够到100MB以上,数据库性能也恢复正常. ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制-转载http://www.cnblogs.com/kubixuesheng/p/5199200.html
JVM系类的文章全部转载自:http://www.cnblogs.com/kubixuesheng/p/5199200.html 特别在此声明.那位博主写的真的很好 ,感谢!! 俗话说,自己写的代码, ...
- PowerShell 远程执行任务
在 linux 中我们可以使用 SSH 执行各种远程操作,同样的在 windows 平台上我们可以通过 PowerShell 获得类似的能力.本文将介绍通过 PowerShell 执行远程操作的基本信 ...
- Ubuntu16.04修改内核启动
写这篇文章一是为了对遇到同样问题的人提供一个参考,二来也是为了自己便于总结和查阅.希望大神勿喷. 好了,废话不多说了,转入正题. 前几天给自己的电脑装了个Ubuntu16.04LTS,自己顺手就把里边 ...
- maven简介及基础使用
一.Maven简介 Maven可译为"知识的积累"."专家",主要服务于基于Java平台的项目构建.依赖管理和项目信息管理. 1.Maven-项目构建工具 ...
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议