文档章节

【99JS手记】之一:nth-child选择器

石佛慈悲
 石佛慈悲
发布于 2014/01/02 23:00
字数 2103
阅读 20
收藏 0


因为本人css很烂很烂,而且水平超烂,所以不敢写特效来误导人,所以,99js手记,是一个纯javascript的频道,利用javascript的各种特性,实现精彩的效果~这一系列的js手记呢,定位的是初中级的js开发人员,目的是多多的写代码~而不是把时间都放在排页面上~在文章中,我会引用大量的资料,希望大家可以认真的阅读。我引用的大多是火狐开发者社区等这样的权威资料,希望大家也养成在上面查阅资料的习惯~

今天开篇,也非常高兴大家能捧场,今天实现一个很有意思的东东

目标: nth-child选择器。

nth-child选择器(不了解可以点这里)对css3与jquery了解的童鞋都应该知道这个选择器。他的语法是

element:nth-child(an + b) { style properties }

这里我们利用js模拟,目标是拿到一个元素集合,利用nthchild(元素集合,an + b)方法来获得想要的结果

一些例子:

  1. nthchild(lista,2n+1),

  2. nthchild(lista,2),

  3. nthchild(lista,3n),

  4. nthchild(lista,n+2),

  5. nthchild(lista,-n+2)

思路:

1.选择器,:顾名思义,首先要有一个范围来选择,那么我们的范围自然就是前面的节点,比如span,或者是已经获取完毕的一个list.(补充知识:domlist,跟arguments(函数参数)一样,是一个类数组,这是啥意思呢?http://shifteleven.com/articles/2007/06/28/array-like-objects-in-javascript

  1. 它具有下标[0][1][2],它可以取到length

  2. 它没有数组的方法,这一点很重要

关于更多的知识可以看:

  1. http://www.cr173.com/html/12597_1.html

  2. http://tuoxie.me/blog/how-to-make-array-like-object-in-javascript

值得补充的是 jquery对象也是个类数组,虽然他有一些数组方法,但都是人为加上去的。扯远了。。

2.我们需要根据“输入”来确定参数。因为我们知道 nth-child(2n+1),nth-child(2), nth-child(3n), 等等的处理办法是完全不同的。这个技术最好的工具是:"正则表达式”由于正则表达式无比艰深,这里提供经典教程 30分钟掌握正则表达式- - http://manual.phpv.net/regular_expression.html利用正则表达式,我们希望获得的是 是否有n? 什么符号?数字是多少

3.分支处理,当我们获得nth-child内的参数后,我们就可以根据情况来处理了。分为以下几种:

  1. 纯数字 2

  2. 倍数 2n

  3. 混合型 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()方法(参考http://www.w3cschool.cn/jsref_push.html)

实现

1.实现正则匹配参数:正则的写法技巧是“找通性,考虑特殊”。

我们分析一下共性跟特殊,2n+1,2,3n,-n+2,n-1共性:格式都是 数字*n +-数字 的形式;特殊 :可能有负号,可能没有n.根据这个思路我写一个正则表达式。也欢迎大家写出更好的来~

(-?\d*)[n]*([+-]\d+)*

  1. *表示前面的匹配 0-无数个

  2. [n]就表示一个n啦

  3. [+-]表示 一个“范围”就是说既有可能匹配加号,也有可能匹配减号

  4. \d表示匹配一个数字

  5. -? 表示 减号匹配0个或者一个,也就是说有可能有

  6. \d+ 加号表示 匹配一个或者多个

加一个括号表示“捕获组” 这是啥意思呢,其实就是让电脑在内存里开几个房子来存储这一小部分~我们之后可以利用match方法等等,再次访问被捕获组匹配到的部分.因为正则表达式是很多javascript函数的核心,所以这里讲得比较细,也希望大家回去多多学习正则。

2 利用正则抓出变量:我们可以利用javascript的match方法,来观察下正则的效果。(match方法的讲解http://www.jb51.net/w3school/js/jsref_match.htm)

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 这是干嘛的呢,请参见http://www.w3school.com.cn/js/jsref_parseInt.asp;之后呢,我们开始遍历我们的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<nodelist.length;i++)

这样写有啥坏处呢?我们仔细分析for的结构.for(初始值;布尔值,表示满足条件后结束循环;操作)这样电脑每次都要计算一下i<nodelist.length这个布尔值不是么。 因此我们可以直接这么写

var l = nodeList.length;for (var i = nodeList.length; i--; )

他的效力跟

for(var i =0;i<nodelist.length;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调试技巧,我这里只用了他很小的一个部分:显示当前的变量是多少。具体的用法可以参考:http://www.ruanyifeng.com/blog/2011/03/firebug_console_tutorial.html.另外ie是不支持console.log的,记得去掉不然会报错.大家可以测试一下。

var lis = document.getElementsByTagName('li')//取得所有的li标签元素,返回一个nodelistnthChild(lis,'2n+1')
nthChild(lis,'2')
nthChild(lis,'n+5')

有关于:nth-child的介绍就先介绍到这,希望这样的杂记对您的工作与学习有所帮助,如果你感兴趣请继续观注w3cplus99js手记的相关更新。

如需转载,烦请注昨出处:http://www.w3cplus.com/js/js/99js-nth-child.html



本文转载自:http://www.w3cplus.com/js/99js-nth-child.html

石佛慈悲
粉丝 26
博文 11
码字总数 1233
作品 0
成都
程序员
私信 提问
CSS3 选择器——伪类选择器

前面花了两节内容分别在《CSS3选择器——基本选择器》和《CSS3选择器——属性选择器》介绍了CSS3选择器中的基本选择器和属性选择器使用方法,今天要和大家一起学习CSS3选择器中的第三部分,也...

石佛慈悲
2013/12/05
33
0
JQuery选择器——子元素筛选选择器和表单元素选择器

子元素筛选选择器和表单元素选择器 1 子元素筛选选择器描述 $(":first-child") 选择所有父级元素下的第一个子元素 $(":last-child") 选择所有父级元素下的最后一个子元素 $(":only-child") 选......

拉考的考拉
2017/11/11
0
0
css选择器nth-child和nth-type-of的区别

前提 因为开发中我们不能总是操作一个dom样式就给一个class显然这是不合理的,我们尽量用其它选择器去代替class选择器 举个例子: 开发中我们会经常使用到这样标签,现在我们需要让第二个li变...

vnues
06/27
0
0
CSS选择器笔记

去年我学jQuery的时候,曾经做过一点选择器(selector)的笔记。 这几天拿出来看了一下,发现很多都忘记了。所以,我决定把它们贴在这里,方便以后查看。这对其他朋友应该也是有用的,毕竟选...

阮一峰
2009/03/12
0
0
CSS3 伪类选择器 nth-child() 的用法

CSS3 伪类选择器 nth-child() 的用法 伪类选择器 nth-child() 在IE6-8和FF3.0-浏览器不支持,CSS3中nth-of-type(n)(比如nth-of-type(1))这个特殊的类选择符可以样式更加个性的标题和段落等,...

a410702849
2016/10/12
10
0

没有更多内容

加载失败,请刷新页面

加载更多

全面兼容IE6/IE7/IE8/FF的CSS HACK写法

浏览器市场的混乱,给设计师造成很大的麻烦,设计的页面兼容完这个浏览器还得兼容那个浏览器,本来ie6跟ff之间的兼容是很容易解决的。加上个ie7会麻烦点,ie8的出现就更头疼了,原来hack ie...

前端老手
9分钟前
3
0
常用快递电子面单批量打印api接口对接demo-JAVA示例

目前有三种方式对接电子面单: 1.快递公司:各家快递公司逐一对接接口 2.菜鸟:支持常用15家快递电子面单打印 3.快递鸟:仅对接一次,支持常用30多家主流快递电子面单打印 目前也是支持批量打...

程序的小猿
12分钟前
5
0
Yii 框架中rule规则必须搭配验证函数才能使用

public $store_id;public $user_id;public $page;public $limit;public $list;public $mch_list;public $cart_id;public $is_community;public $shop_id;public $cart_typ......

chenhongjiang
15分钟前
2
0
Flutter使用Rammus实现阿里云推送

前言: 最近新的Flutter项目有“阿里云推送通知”的需求,就是Flutter的App启动后检测到有新的通知,点击通知栏然后跳转到指定的页面。在这里我使用的是第三方插件Rammus来实现通知的推送,之...

EmilyWu
15分钟前
38
0
Knative 实战:三步走!基于 Knative Serverless 技术实现一个短网址服务

短网址顾名思义就是使用比较短的网址代替很长的网址。维基百科上面的解释是这样的: 短网址又称网址缩短、缩短网址、URL 缩短等,指的是一种互联网上的技术与服务,此服务可以提供一个非常短...

阿里巴巴云原生
30分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部