本文共 3428 字,大约阅读时间需要 11 分钟。
本来是打算参考,然后将里面想要的部分抽出来做函数,随调随用。
但后面发现这种写法重复代码太多,代码不整洁,于是就打算模仿下zepto的写法,挑出些比较实用的方法,造一下轮子。
起名叫“”,已经放到了。
简单的做了封装,本来也想使用“$”相关的符号,但看来看去不是很合适,就用大写的“S”替代。
在造轮子的过程中,了解到了以前不知道的Element、Array等相关的方法或属性,这也是种收获。
同时引进了单元测试工具,通过加载其中的一个组件,就可以测试DOM了。
1)Element与Node
(节点)是DOM层次结构中的任何类型的对象的通用名称,Node有很多类型,常用的如下:
继承了Node类,也就是说Element是Node多种类型中的一种,nodeType=1的Node就是Element,并且Element还有很多自己的属性和方法。
2)children与childNodes
Element类中的返回nodeType为1的子元素集合,该集合为一个即时更新的(live)。
Node类中返回nodeType为1或3的子元素的集合,该集合为一个即时更新的(live)。
inner
分别将outter中的两个值打印出,,如下所示:
3)Element.matches()
表示如果当前元素能被指定的css选择器查找到,则返回true,否则返回false。这个方法在不同浏览器中需要使用前缀。
是个css选择器字符串,语法与相同,同样可以。function matches(element, selector) { var matchesSelector = element.webkitMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.matchesSelector; return matchesSelector.call(element, selector)}var ismatch = matches(inner, "#inner");
4)Array相关方法
有众多方法,平时会用做数组转换、做迭代,在zepto源码中用到了好几个我平时没怎么用的方法。
:将传入的数组或非数组值与原数组合并,组成一个新的数组并返回。
:使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组。
:接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。
:测试数组中的某些元素是否通过了指定函数的测试。
:测试数组的所有元素是否都通过了指定函数的测试。
:返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组。
zepto是将普通的元素包装了起来,在原型链中添加了很多方法,而通过“$”查找到的是个数组。
我自己封装的就用“S”来代表“$”符号。
例如$("div")调用上面的html代码,返回是将是下面一个伪数组,如果要变成数组就要手动的做“slice”操作。
1)S.matches
前面讲到过,用来做选择器匹配,对于不支持matches的浏览器,zepto中做了些兼容操作,源码在左右。
在zepto经常引用的find、filter、is、closest等操作中就会使用这个方法。
2)S.qsa
根据输入的选择器,做匹配查询,使用、、或。
其实通过这个方法,可以选择最合适的匹配方法,选择器的语法也能做到与jQuery类似,源码在左右。
3)S.extend
通过源对象扩展目标对象属性,源对象属性将覆盖目标对象属性,源码在左右。
在zepto中的extend中,如果参数是个对象,那么浅复制仅仅是复制一个引用,深复制是复制内容。
var source = {0:1, 3:{4:'a', 5:'b'}};var target = {};extend(target, source);//第三个值为true,是深复制source[3][4] = 'c';console.log(target);console.log(source);
上面是浅复制,修改source,target也会改变,左边是target,右边source。
如果是深复制,就不会改变。
我想简单点使用,就直接修改为浅复制吧,但我会过个的判断,过滤原型链上的属性或方法。
function extend(target, source) { for (key in source) { if (source[key] !== undefined && source.hasOwnProperty(key)) target[key] = source[key]; }}
4)S.contains
是类中的方法,返回一个boolean表示传入的节点是否是子节点。
zepto的代码中,还做了兼容性处理,可以直接拿来用,源码在左右。
5)S.children
查找子元素的兼容方法,这里面涉及到两个属性,“”和“”。
前者返回集合,可以不用做NodeType的判断。
而后者返回的是集合,会返回两种类型的NodeType,1和3,所以要做判断过滤。
6)S.map
本来就是想直接用数组的map方法,但是后面在通过map集合后,要做“null”的过滤,并且还要做“concat”操作。
因为map后的集合会出现“[Array[2],Array[3]]”的方式,我只需要一维数组即可。
7)S.init
初始化操作,通过一些逻辑操作,获取集合,再做“new iSelector”操作,做一层包裹。
接下来的方法都是在S.fn内,也就是会放到iSelector.prototype中。
1)filter
一个一维的节点数组,通过特定的函数或选择器过滤后,返回一个新的数组。
在children、siblings、prev和next中也会引用这个方法。
2)find
查找元素的子节点,就是在引用上面的qsa公共方法,在某个元素下面执行等。
3)closest
返回最先匹配选择器的一个祖先元素,通过循环“”,再用上面的“S.matches”匹配指定的选择器。
4)children
获取直接子元素,通过公共的“S.children”获取到元素下面的子元素,再通过“filter”过滤指定的选择器。
5)siblings
获取兄弟元素。没有直接的库方法,通过点小技巧,先获取父元素,然后再“S.children”获取到此元素的子元素,再通过“filter”过滤指定的选择器。
6)prev与next
获取上一个元素与下一个元素,这里用到了两个Element类中的属性,“”和“”
7)before与after
将元素插入到前面与后面,原生方法中只有“”,如果要插入到后面就要模拟一下。
通过前面的“next”方法获取当前元素的下一个元素,然后插入到这个元素之前,就达到插入到后面的效果。
1)html
既可做赋值也可做获取,使用了原生的“”。
2)attr与removeAttr
获取属性与移除属性,使用了原生的方法“”和“”。
3)setClass
设置与删除元素的class值,Element类中的可以获取当前元素的class值。
将这个值用“(/\s+/)”来分割,然后在数组中与输入的做匹配。
4)hasClass
判断元素的class值是否存在,也用到了正则“new RegExp('(^|\\s)'+name+'(\\s|$)')”,用这个来对比是否存在。
灵活运用正则可以简化很多工作,关于正则更多信息可以参考《》
单元测试使用了,还使用了单元测试的一个组件,简单的引用后就可直接使用。
目录结构中fixtures保存是html文件,测试DOM操作的时候,操作的html就是这里面的。
双击index.html就可以看到测试结果。
参考资料:
本文转自 咖啡机(K.F.J) 博客园博客,原文链接http://www.cnblogs.com/strick/p/5357210.html:,如需转载请自行联系原作者