因为本人css很烂很烂,而且水平超烂,所以不敢写特效来误导人,所以,99js手记,是一个纯javascript的频道,利用javascript的各种特性,实现精彩的效果~这一系列的js手记呢,定位的是初中级的js开发人员,目的是多多的写代码~而不是把时间都放在排页面上~在文章中,我会引用大量的资料,希望大家可以认真的阅读。我引用的大多是火狐开发者社区等这样的权威资料,希望大家也养成在上面查阅资料的习惯~
今天开篇,也非常高兴大家能捧场,今天实现一个很有意思的东东
目标: nth-child选择器。
nth-child选择器(不了解可以点)对css3与jquery了解的童鞋都应该知道这个选择器。他的语法是
element:nth-child(an + b) { style properties }
这里我们利用js模拟,目标是拿到一个元素集合,利用nthchild(元素集合,an + b)方法来获得想要的结果
一些例子:
nthchild(lista,2n+1),
nthchild(lista,2),
nthchild(lista,3n),
nthchild(lista,n+2),
nthchild(lista,-n+2)
思路:
1.选择器,:顾名思义,首先要有一个范围来选择,那么我们的范围自然就是前面的节点,比如span,或者是已经获取完毕的一个list.(补充知识:domlist,跟arguments(函数参数)一样,是一个类数组,这是啥意思呢?
它具有下标[0][1][2],它可以取到length
它没有数组的方法,这一点很重要
关于更多的知识可以看:
值得补充的是 jquery对象也是个类数组,虽然他有一些数组方法,但都是人为加上去的。扯远了。。
2.我们需要根据“输入”来确定参数。因为我们知道 nth-child(2n+1),nth-child(2), nth-child(3n), 等等的处理办法是完全不同的。这个技术最好的工具是:"正则表达式”由于正则表达式无比艰深,这里提供经典教程 30分钟掌握正则表达式- - 利用正则表达式,我们希望获得的是 是否有n? 什么符号?数字是多少
3.分支处理,当我们获得nth-child内的参数后,我们就可以根据情况来处理了。分为以下几种:
纯数字 2
倍数 2n
混合型 n+2,2n+1之类
4 处理思路:x*n+y,n从0开始++,当然(x*n+y)要>0那我们可以设结果是 index 则 x*n+y=indexn = (index-y) / x ; 也就是说 x可以整除 index-y那么,当result满足:(index-y) % x === 0 且n >= 0,就是符合条件的了.之后我们遍历所有节点,判断下数量即可~另外注意一点,nth-child里面是从1开始的,所以遍历的时候一定要记得序号从1开始!
5 处理结果: 选择器通常返回的是一个数组,那么我们应该也要返回一个数组。可以利用空数组的push()方法(参考)
实现
1.实现正则匹配参数:正则的写法技巧是“找通性,考虑特殊”。
我们分析一下共性跟特殊,2n+1,2,3n,-n+2,n-1共性:格式都是 数字*n +-数字 的形式;特殊 :可能有负号,可能没有n.根据这个思路我写一个正则表达式。也欢迎大家写出更好的来~
(-?\d*)[n]*([+-]\d+)*
*表示前面的匹配 0-无数个
[n]就表示一个n啦
[+-]表示 一个“范围”就是说既有可能匹配加号,也有可能匹配减号
\d表示匹配一个数字
-? 表示 减号匹配0个或者一个,也就是说有可能有
\d+ 加号表示 匹配一个或者多个
加一个括号表示“捕获组” 这是啥意思呢,其实就是让电脑在内存里开几个房子来存储这一小部分~我们之后可以利用match方法等等,再次访问被捕获组匹配到的部分.因为正则表达式是很多javascript函数的核心,所以这里讲得比较细,也希望大家回去多多学习正则。
2 利用正则抓出变量:我们可以利用javascript的match方法,来观察下正则的效果。(match方法的讲解)
var reg = /(-?\d*)[n]*([+-]\d+)*/var a = '2'a.match(reg)//["2", "2", undefined]var b = '2n+1'b.match(reg)//["2n+1", "2", "+1"]var c= '-n+1'c.match(reg)//["-n+1", "-", "+1"]var d = '10n+10'd.match(reg)//["10n+10", "10", "+10"]
非常明显,match的返回结果 在不同情况下表现是不同的。返回结果是一个数组,数组的第一项是“全局匹配”,即正则全部匹配到的内容,第二项跟第三项是我们所说的“捕获组” 可以叫做 捕获组1号,捕获组2号,再回头看
var reg = /(-?\d*)[n]*([+-]\d+)*/
是不是就明白多了。。
3开始处理:我们的核心函数利用拿到的值做分支判断
var reg = /(-?\d*)[n]*([+-]\d+)*/,m = selector.match(reg);if (selector === m[1]) { // 纯数字 return [nodeList[(parseInt(m[1]) - 1)]];}function filter(index) { //过滤器函数 console.log('m1'+m[1],'m2'+m[2]) x = m[1];//直接把n前面的值赋给x y= m[2]; if (m[2]) { // n后面存在y if ('' === m[1]) { // n前面木有负号 xn+y x=1 x= 1; y= m[2] } else if ('-' === m[1]) { // n前面有负号 x = -1; y= m[2] } } else { //n后面不存在y y = 0; } var n = (index - parseInt(y)) / parseInt(x);//开始计算 console.log('x'+x,'y'+y,n+'n') // 正整数返回true return (n === parseInt(n) && n >= 0) ? true : false;}
以上用了一个函数 parseInt 这是干嘛的呢,请参见;之后呢,我们开始遍历我们的dom节点。
var result = []; //存储结果var l = nodeList.length;//缓存for (var i =1; i<=l; i++) {//这里从1开始! console.log(i,filter(i)) if (filter(i)) { result.push(nodeList[i-1])//注意了nodelist下标从0开始,所以要-1! }}
补充(:这里我再次需要讲解一个东西叫做高性能循环.一般我们写循环通常是这样的
for(var i =0;i
这样写有啥坏处呢?我们仔细分析for的结构.for(初始值;布尔值,表示满足条件后结束循环;操作)这样电脑每次都要计算一下i<nodelist.length这个布尔值不是么。 因此我们可以直接这么写
var l = nodeList.length;for (var i = nodeList.length; i--; )
他的效力跟
for(var i =0;i
是一样的,但是性能更高。写了这么多,我们可以把完整的函数放出来了
function nthChild(nodeList, selector) { var x, y; //xn+y var reg = /(-?\d*)[n]*([+-]\d+)*/, m = selector.match(reg); if (selector === m[1]) { // 纯数字 return [nodeList[(parseInt(m[1]) - 1)]]; }function filter(index) { //过滤器函数 console.log('m1' + m[1], 'm2' + m[2]) x = m[1]; //直接把n前面的值赋给x y = m[2]; if (m[2]) { // n后面存在y if ('' === m[1]) { // n前面木有负号 xn+y x=1 x = 1; y = m[2] } else if ('-' === m[1]) { // n前面有负号 x = -1; y = m[2] } else { //n后面不存在y y = 0; } var n = (index - parseInt(y)) / parseInt(x); //开始计算 console.log('x' + x, 'y' + y, n + 'n') // 正整数返回true return (n === parseInt(n) && n >= 0) ? true : false; } var result = []; //存储结果 var l = nodeList.length; //缓存 for (var i = 1; i <= l; i++) { //这里从1开始! console.log(i, filter(i)) if (filter(i)) { result.push(nodeList[i - 1]) //注意了nodelist下标从0开始,所以要-1! } } return result;}
大家注意到很多console.log了么,这是常用的javascript调试技巧,我这里只用了他很小的一个部分:显示当前的变量是多少。具体的用法可以参考:.另外ie是不支持console.log的,记得去掉不然会报错.大家可以测试一下。
var lis = document.getElementsByTagName('li')//取得所有的li标签元素,返回一个nodelistnthChild(lis,'2n+1')nthChild(lis,'2')nthChild(lis,'n+5')
有关于:nth-child的介绍就先介绍到这,希望这样的杂记对您的工作与学习有所帮助,如果你感兴趣请继续观注中的相关更新。
如需转载,烦请注昨出处: