专注于前端开发, 追求更好的用户体验, 更好的开发体验 [长沙前端QQ群:234746733]

javascript 实现 css 的 nth-child选择符

最近精简了JQuery,精简到33KB,一些功能肯定被K掉了。保留了常用的:
ready, attr, data, css, html, text, val, empty, append, siblings, wrap, trigger, bind, unbind, delegate, mouseenter, mouseleave, anim, stop, ajax, jsonp等等。
除了attr,data,css用了JQ的,并做了些改动,其他的基本都没在JQ的源码上精简,算个山寨货?。。。
功能肯定没JQ强大,但是文件大小从JQ1.6的80K到30K,用在一些不是特别复杂的应用上还是不错的。
语法也是用了链式操作,因为一些方法没参考JQ源码,所以有些语法和JQ不一样了。JQ的一些插件也不能直接用了,不过改改插件,基本上还是可以用的。

因为选择器没采用用sizzle,所以没法用一些高级的选择符,比如odd,even,nth-child,这些就需要另外写方法实现了。
odd,even的实现比较省事,取奇偶就可以了,i % 2的余数是0还是1就OK。

nth-child的实现费了一些力,不仅要匹配允许的选择符,还要返回符合规范的结果。
如果不知道CSS的nth-child选择符可以自己Search一下,偶就不介绍了。
一些例子:nth-child(2n+1), nth-child(2), nth-child(3n), nth-child(n+2),nth-child(-n+2)

代码如下:

  1. function nthChild(nodeList, selector ) {
  2.         var ret = [],
  3.                 reg = /(-?\d*)[n]*([+-]\d+)*/,
  4.                 m = selector.match(reg);
  5.         if (selector === m[1]) { // nth-child:(2) - 纯数字,直接返回
  6.                 return [nodeList[(parseInt(m[1])-1)]];
  7.         }
  8.         var filter = function(i){
  9.                 ++i; //nth从1开始, elem从0开始,elem的index要+1
  10.                 if (m[2]) { // 类似:nth-child:(-2n-1) / nth-child(n+2)
  11.                         if ('' === m[1]){ // nth-child(n+2)
  12.                                 m[1] = 1;
  13.                         }else if ('-' === m[1]) { // nth-child(-n+2)
  14.                                 m[1] = -1;
  15.                         }// else nth-child(-2n-1) / nth-child(2n+10)
  16.                 }else { // nth-child:(2n)
  17.                         m[2] = 0;
  18.                 }
  19.                 var n = (i-parseInt(m[2])) / parseInt(m[1]);
  20.                 // 正整数返回true
  21.                 return ( n === parseInt(n) && n >= 0) ? true : false;
  22.         }
  23.         each(nodeList, function(i){ //each 方法需要单独写
  24.                 if (filter(i)) {
  25.                         ret.push(this)
  26.                 }
  27.         });
  28.         return ret;
  29. }

实现nth-child的思路:

nth-child的公式为:nth-child(x*n+y);
n从0开始++,(x*n+y)要>0
x *n + y = i; // n,为自然数,从0开始; i为要取的第几个元素(正整数)
上面得到:n = (i-y) / x ; 整除,余0
那么,当i满足:(i-y) % x === 0 && (i-y) / x >= 0,就是符合条件的了

使用:

  1. function each( obj, fn ) {
  2.         var i = 0, len = obj.length, val;
  3.         for (; i < len; i++) {
  4.                 val = fn.call(obj[i], i, obj[i]);
  5.                 if ( val === false ) break;
  6.         }
  7. }
  8. var list = nthChild(document.getElementsByTagName("li"), '2n+1'); //奇数行
  9. //使用FF/CM/OP/IE9等支持nth-child选择符的浏览器,得到NodeList的结果,可以用来与nthChild的结果比较
  10.         //比如:document.querySelectorAll('li:nth-child(2n+1)')
  11. each(list, function(){ this.className = 'selected'; }); //给奇数行设置class=selected

/ 分类: 开发,实践 / TrackBackhttps://xhl.me/archives/nth-child-selector-width-js/trackback标签: css, javascript

添加新评论 »