一个普通的 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元素的特性 ...
随机推荐
- [leetcode-630-Course Schedule III]
There are n different online courses numbered from 1 to n. Each course has some duration(course leng ...
- IOS 状态栏(UIStatusBar)
ios上状态栏指的屏幕顶端的20像素高的部分 状态栏分前景和背景两部分 前景部分:就是指的显示电池.时间等部分: 背景部分:就是显示白色或者图片的背景部分: 如下图:前景部分为黑色字体,背景部分为白色 ...
- python实现希尔排序(已编程实现)
希尔排序: 观察一下”插入排序“:其实不难发现她有个缺点: 如果当数据是”5, 4, 3, 2, 1“的时候,此时我们将“无序块”中的记录插入到“有序块”时,估计俺们要崩盘, 每次插入都要移动位置,此 ...
- docker中执行sed: can't move '/etc/resolv.conf73UqmG' to '/etc/resolv.conf': Device or resource busy错误的处理原因及方式
错误现象 在docker容器中想要修改/etc/resolv.conf中的namesever,使用sed命令进行执行时遇到错误: / # sed -i 's/192.168.1.1/192.168.1 ...
- ionicangular 成长日记
//首先配置文件ionic.bundle.min.jsionic.min.css" //创建一个angular控制器,控制器给body/html都可以angular.module('myap ...
- 基于vue2.0的一个豆瓣电影App
1.搭建项目框架 使用vue-cli 没安装的需要先安装 npm intall -g vue-cli 使用vue-cli生成项目框架 vue init webpack-simple vue-movie ...
- java用户界面窗口
java用户界面窗口 窗口框 代码如下: package Day08; import java.awt.Color;import java.awt.FlowLayout;import java.awt ...
- VMware虚拟机下Ubuntu连不上网解决
虚拟机:VMware® Workstation 12 Pro Ubuntu: 14.04 问题描述:电脑从公司拿到家打开Ubuntu之后,打开自带Firefox浏览器,显示连接不上网,终端下ping ...
- 20170717_python_爬虫_网页数据解析_BeautifulSoup_数据保存_pymysql
上午废了老大劲成功登陆后,下午看了下BeautifulSoup和pymysql,晚上记录一下 自己电脑装的sublime,字体颜色竟然拷贝不下来 - - 写的过程中遇到了很多问题: 1.模拟登陆部分 ...
- 虚拟机Linux系统下配置网络
虚拟机上安装Redhat9.0后是没有网络的,而本来的Windows系统是可以上网的,此时想在Redhat上网就需要在Linux系统上配置网络,以下是笔者自己配置的一点心得. 1.电脑本机系统打开网络 ...