一个普通的 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元素的特性 ...
随机推荐
- Bootstrap列表组
前面的话 列表组是Bootstrap框架新增的一个组件,可以用来制作列表清单.垂直导航等效果,也可以配合其他的组件制作出更漂亮的组件.本文将详细介绍Bootstrap列表组 基础列表组 基础列表组,看 ...
- Angular基础(二)
双向数据 利用angular把input框里面的值和h3的值绑定在一起.在input里输入内容,内容会在h3标签里显示出来. 具体效果请看下面代码: <!DOCTYPE html> ...
- 深度理解Node.js单线程模型
Node.js采用 事件驱动 和 异步I/O 的方式,实现了一个单线程.高并发的运行时环境,而单线程就意味着同一时间只能做一件事,那么Node.js如何利用单线程来实现高并发和异步I/O?本文将围绕这 ...
- FineReport中如何对cpt模板加密
1. 描述 FR客户使用FineReport报表并将其集成到自己的产品中,然后提供给最终用户使用,最终用户可以预览FR模板,但是不能打开模板进行设计修改. FineReport提供了cpt模板Des加 ...
- 小哈学Python-第一课:基本介绍
Python前世今生 python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC ...
- php与MySQL(基本操作)
PHP连接 MySQL 在我们访问 MySQL 数据库前,我们需要先连接到数据库服务器,连接服务器,我们使用mysqli_connect()函数. 在使用这个函数之前,我们首先来看一下这个函数的语法: ...
- JS - dateFormat
// date必填, pattern默认'yyyy-MM-dd HH:mm:ss'function dateFormat (date, pattern) { var week = {'0':'日', ...
- 常用http响应报文分析
这是我在使用Asp.Net的时候,整理的的一些关于Http响应报文的分析笔记,零零散散的记录, 现在贴出来,抛砖引玉,如果有什么不对或者不严谨的地方,请各位大神不吝赐教. 一.HTTP响应码响应码由三 ...
- 51nod_1417:天堂里的游戏
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1417 假设 ans=n/m,C=(A+B)/2 若出正面 ...
- bzoj2120: 数颜色 [莫队][分块]
Description 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜 ...
知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议