js 实现css风格选择器(压缩后2KB)


Posted in Javascript onJanuary 12, 2012

近日在做一些OA前端界面,为了更好管理页面代码想写个js选择器,写着写着发现很费力,索性在网上找找看,功夫不负有心人, 找到一个mini css选择器,且性能不凡:以下代码是压缩后的,仅2KB。

var $=(function(){var b=/(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig,g=/^(?:[\w\-_]+)?\.([\w\-_]+)/,f=/^(?:[\w\-_]+)?#([\w\-_]+)/,j=/^([\w\*\-_]+)/,h=[null,null];function d(o,m){m=m||document;var k=/^[\w\-_#]+$/.test(o);if(!k&&m.querySelectorAll){return c(m.querySelectorAll(o))}if(o.indexOf(",")>-1){var v=o.split(/,/g),t=[],s=0,r=v.length;for(;s<r;++s){t=t.concat(d(v[s],m))}return e(t)}var p=o.match(b),n=p.pop(),l=(n.match(f)||h)[1],u=!l&&(n.match(g)||h)[1],w=!l&&(n.match(j)||h)[1],q;if(u&&!w&&m.getElementsByClassName){q=c(m.getElementsByClassName(u))}else{q=!l&&c(m.getElementsByTagName(w||"*"));if(u){q=i(q,"className",RegExp("(^|\\s)"+u+"(\\s|$)"))}if(l){var x=m.getElementById(l);return x?[x]:[]}}return p[0]&&q[0]?a(p,q):q}function c(o){try{return Array.prototype.slice.call(o)}catch(n){var l=[],m=0,k=o.length;for(;m<k;++m){l[m]=o[m]}return l}}function a(w,p,n){var q=w.pop();if(q===">"){return a(w,p,true)}var s=[],k=-1,l=(q.match(f)||h)[1],t=!l&&(q.match(g)||h)[1],v=!l&&(q.match(j)||h)[1],u=-1,m,x,o;v=v&&v.toLowerCase();while((m=p[++u])){x=m.parentNode;do{o=!v||v==="*"||v===x.nodeName.toLowerCase();o=o&&(!l||x.id===l);o=o&&(!t||RegExp("(^|\\s)"+t+"(\\s|$)").test(x.className));if(n||o){break}}while((x=x.parentNode));if(o){s[++k]=m}}return w[0]&&s[0]?a(w,s):s}var e=(function(){var k=+new Date();var l=(function(){var m=1;return function(p){var o=p[k],n=m++;if(!o){p[k]=n;return true}return false}})();return function(m){var s=m.length,n=[],q=-1,o=0,p;for(;o<s;++o){p=m[o];if(l(p)){n[++q]=p}}k+=1;return n}})();function i(q,k,p){var m=-1,o,n=-1,l=[];while((o=q[++m])){if(p.test(o[k])){l[++n]=o}}return l}return d})();

把原版也分享下:
/** 
* "mini" Selector Engine 
* Copyright (c) 2009 James Padolsey 
* ------------------------------------------------------- 
* Dual licensed under the MIT and GPL licenses. 
* - http://www.opensource.org/licenses/mit-license.php 
* - http://www.gnu.org/copyleft/gpl.html 
* ------------------------------------------------------- 
* Version: 0.01 (BETA) 
*/ 
var mini = (function(){ 
var snack = /(?:[\w\-\\.#]+)+(?:\[\w+?=([\'"])?(?:\\\1|.)+?\1\])?|\*|>/ig, 
exprClassName = /^(?:[\w\-_]+)?\.([\w\-_]+)/, 
exprId = /^(?:[\w\-_]+)?#([\w\-_]+)/, 
exprNodeName = /^([\w\*\-_]+)/, 
na = [null,null]; 
function _find(selector, context) { 
/** 
* This is what you call via x() 这是你们所谓的经x 
* Starts everything off... 开始上所有的 
*/ 
context = context || document; 
var simple = /^[\w\-_#]+$/.test(selector); 
if (!simple && context.querySelectorAll) { 
return realArray(context.querySelectorAll(selector)); 
} 
if (selector.indexOf(',') > -1) { 
var split = selector.split(/,/g), ret = [], sIndex = 0, len = split.length; 
for(; sIndex < len; ++sIndex) { 
ret = ret.concat( _find(split[sIndex], context) ); 
} 
return unique(ret); 
} 
var parts = selector.match(snack), 
part = parts.pop(), 
id = (part.match(exprId) || na)[1], 
className = !id && (part.match(exprClassName) || na)[1], 
nodeName = !id && (part.match(exprNodeName) || na)[1], 
collection; 
if (className && !nodeName && context.getElementsByClassName) { 
collection = realArray(context.getElementsByClassName(className)); 
} else { 
collection = !id && realArray(context.getElementsByTagName(nodeName || '*')); 
if (className) { 
collection = filterByAttr(collection, 'className', RegExp('(^|\\s)' + className + '(\\s|$)')); 
} 
if (id) { 
var byId = context.getElementById(id); 
return byId?[byId]:[]; 
} 
} 
return parts[0] && collection[0] ? filterParents(parts, collection) : collection; 
} 
function realArray(c) { 
/** 
* Transforms a node collection into 转换一个节点收藏 
* a real array 一个真正的阵列 
*/ 
try { 
return Array.prototype.slice.call(c); 
} catch(e) { 
var ret = [], i = 0, len = c.length; 
for (; i < len; ++i) { 
ret[i] = c[i]; 
} 
return ret; 
} 
} 
function filterParents(selectorParts, collection, direct) { 
/** 
* This is where the magic happens. 这就是魔法发生 
* Parents are stepped through (upwards) to 父母们加紧通过向上 
* see if they comply with the selector. 看看他们是否符合选择器 
*/ 
var parentSelector = selectorParts.pop(); 
if (parentSelector === '>') { 
return filterParents(selectorParts, collection, true); 
} 
var ret = [], 
r = -1, 
id = (parentSelector.match(exprId) || na)[1], 
className = !id && (parentSelector.match(exprClassName) || na)[1], 
nodeName = !id && (parentSelector.match(exprNodeName) || na)[1], 
cIndex = -1, 
node, parent, 
matches; 
nodeName = nodeName && nodeName.toLowerCase(); 
while ( (node = collection[++cIndex]) ) { 
parent = node.parentNode; 
do { 
matches = !nodeName || nodeName === '*' || nodeName === parent.nodeName.toLowerCase(); 
matches = matches && (!id || parent.id === id); 
matches = matches && (!className || RegExp('(^|\\s)' + className + '(\\s|$)').test(parent.className)); 
if (direct || matches) { break; } 
} while ( (parent = parent.parentNode) ); 
if (matches) { 
ret[++r] = node; 
} 
} 
return selectorParts[0] && ret[0] ? filterParents(selectorParts, ret) : ret; 
} 
var unique = (function(){ 
var uid = +new Date(); 
var data = (function(){ 
var n = 1; 
return function(elem) { 
var cacheIndex = elem[uid], 
nextCacheIndex = n++; 
if(!cacheIndex) { 
elem[uid] = nextCacheIndex; 
return true; 
} 
return false; 
}; 
})(); 
return function(arr) { 
/** 
* Returns a unique array返回一个独特的阵列 
*/ 
var length = arr.length, 
ret = [], 
r = -1, 
i = 0, 
item; 
for (; i < length; ++i) { 
item = arr[i]; 
if (data(item)) { 
ret[++r] = item; 
} 
} 
uid += 1; 
return ret; 
}; 
})(); 
function filterByAttr(collection, attr, regex) { 
/** 
* Filters a collection by an attribute. 一个收集过滤器一个属性 
*/ 
var i = -1, node, r = -1, ret = []; 
while ( (node = collection[++i]) ) { 
if (regex.test(node[attr])) { 
ret[++r] = node; 
} 
} 
return ret; 
} 
return _find; 
})();

以上代码支持css风格样式写法包括:
div 
.example 
body div 
div, p 
div, p, .example 
div p 
div > p 
div.example 
ul .example 
#title 
h1#title 
div #title 
ul.foo > * span
Javascript 相关文章推荐
RGB颜色值转HTML十六进制(HEX)代码的JS函数
Apr 25 Javascript
三级下拉菜单的js实现代码
May 23 Javascript
jQuery设置div一直在页面顶部显示的方法
Oct 24 Javascript
使用JSLint提高JS代码质量方法分享
Dec 16 Javascript
JS文本获得焦点清除文本文字的示例代码
Jan 13 Javascript
JS+CSS相对定位实现的下拉菜单
Oct 06 Javascript
浅谈Angular中ngModel的$render
Oct 24 Javascript
jQuery实现的五星点评功能【案例】
Feb 18 jQuery
JavaScript数据结构与算法之二叉树插入节点、生成二叉树示例
Feb 21 Javascript
我要点爆”微信小程序云开发之项目建立与我的页面功能实现
May 26 Javascript
vue实现抖音时间转盘
Sep 08 Javascript
基于JS实现table导出Excel并保留样式
May 19 Javascript
js日历功能对象
Jan 12 #Javascript
关于 文本框默认值 的操作js代码
Jan 12 #Javascript
新发现一个骗链接的方法(js读取cookies)
Jan 11 #Javascript
JS读取cookies信息(记录用户名)
Jan 10 #Javascript
判断对象是否Window的实现代码
Jan 10 #Javascript
jQuery在IE下使用未闭合的xml代码创建元素时的Bug介绍
Jan 10 #Javascript
javascript中onmouse事件在div中失效问题的解决方法
Jan 09 #Javascript
You might like
php使用websocket示例详解
2014/03/12 PHP
兼容各大浏览器带关闭按钮的漂浮多组图片广告代码
2014/06/05 PHP
php用ini_get获取php.ini里变量值的方法
2015/03/04 PHP
php基于自定义函数记录log日志方法
2017/07/21 PHP
jquery 插件学习(二)
2012/08/06 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
Nodejs实现的一个静态服务器实例
2014/12/06 NodeJs
jQuery+CSS3实现树叶飘落特效
2015/02/01 Javascript
JavaScript使用shift方法移除素组第一个元素实例分析
2015/04/06 Javascript
jquery实现平滑的二级下拉菜单效果
2015/08/26 Javascript
任意Json转成无序列表的方法示例
2016/12/09 Javascript
jQuery实现鼠标滑过预览图片大图效果的方法
2017/04/26 jQuery
分享vue.js devtools遇到一系列问题
2017/10/24 Javascript
浅谈vue,angular,react数据双向绑定原理分析
2017/11/28 Javascript
video.js 一个页面同时播放多个视频的实例代码
2018/11/27 Javascript
在vue项目中引入highcharts图表的方法
2019/01/21 Javascript
详解基于electron制作一个node压缩图片的桌面应用
2019/01/29 Javascript
nodejs二进制与Buffer的介绍与使用
2019/07/11 NodeJs
vue 实现微信浮标效果
2019/09/01 Javascript
JavaScript 自定义html元素鼠标右键菜单功能
2019/12/02 Javascript
JS中的模糊查询功能
2019/12/08 Javascript
vue学习之Vue-Router用法实例分析
2020/01/06 Javascript
JS实现单张或多张图片持续无缝滚动的示例代码
2020/05/10 Javascript
weui上传多图片,压缩,base64编码的示例代码
2020/06/22 Javascript
如何使用JavaScript实现无缝滚动自动播放轮播图效果
2020/08/20 Javascript
Python脚本判断 Linux 是否运行在虚拟机上
2015/04/25 Python
Python中字典和集合学习小结
2017/07/07 Python
python中使用xlrd读excel使用xlwt写excel的实例代码
2018/01/31 Python
python求一个字符串的所有排列的实现方法
2020/02/04 Python
使用Keras实现简单线性回归模型操作
2020/06/12 Python
OpenCV4.1.0+VS2017环境配置的方法步骤
2020/07/09 Python
Python基于Serializer实现字段验证及序列化
2020/11/04 Python
python实现学生信息管理系统源码
2021/02/22 Python
如何使JavaScript休眠或等待
2021/04/27 Javascript
mysql事务对效率的影响分析总结
2021/10/24 MySQL
Redis基本数据类型List常用操作命令
2022/06/01 Redis