专注于WEB前端开发, 追求更好的用户体验, 更好的开发体验 [长沙前端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)

代码如下:

function nthChild(nodeList, selector ) {
	var ret = [],
		reg = /(-?\d*)[n]*([+-]\d+)*/,
		m = selector.match(reg);
	if (selector === m[1]) { // nth-child:(2) - 纯数字,直接返回
		return [nodeList[(parseInt(m[1])-1)]];
	}
	var filter = function(i){
		++i; //nth从1开始, elem从0开始,elem的index要+1
		if (m[2]) { // 类似:nth-child:(-2n-1) / nth-child(n+2)
			if ('' === m[1]){ // nth-child(n+2)
				m[1] = 1;
			}else if ('-' === m[1]) { // nth-child(-n+2)
				m[1] = -1;
			}// else nth-child(-2n-1) / nth-child(2n+10)
		}else { // nth-child:(2n)
			m[2] = 0;
		}
		var n = (i-parseInt(m[2])) / parseInt(m[1]);
		// 正整数返回true
		return ( n === parseInt(n) && n >= 0) ? true : false;
	}
	each(nodeList, function(i){ //each 方法需要单独写
		if (filter(i)) {
			ret.push(this)
		}
	});
	return ret;
}

实现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,就是符合条件的了

使用:

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

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

添加新评论 »