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 相关文章推荐
window.onload 加载完毕的问题及解决方案(下)
Jul 09 Javascript
javascript 带有滚动条的表格,标题固定,带排序功能.
Nov 13 Javascript
jQuery版仿Path菜单效果
Dec 15 Javascript
JS去除字符串两端空格的简单实例
Dec 27 Javascript
jquery1.10给新增元素绑定事件的方法
Mar 06 Javascript
jquery zTree异步加载简单实例讲解
Feb 25 Javascript
jQuery中使用animate自定义动画的方法
May 29 Javascript
js实现弹窗居中的简单实例
Oct 09 Javascript
JS路由跳转的简单实现代码
Sep 21 Javascript
vue 双向数据绑定的实现学习之监听器的实现方法
Nov 30 Javascript
vue实现form表单与table表格的数据关联功能示例
Jan 29 Javascript
vue项目中js-cookie的使用存储token操作
Nov 13 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常用函数的用法详解
2013/05/10 PHP
CI框架开发新浪微博登录接口源码完整版
2014/05/28 PHP
ThinkPHP控制器里javascript代码不能执行的解决方法
2014/11/22 PHP
Yii CGridView用法实例详解
2016/07/12 PHP
jquery插件开发方法(初学者)
2012/02/03 Javascript
jQuery操作input type=radio的实现代码
2012/06/14 Javascript
基于jQuery的获取标签名的代码
2012/07/16 Javascript
js判断选择的时间是否大于今天的代码
2013/08/20 Javascript
jtable列中自定义button示例代码
2013/11/21 Javascript
学习JavaScript设计模式(策略模式)
2015/11/26 Javascript
jquery对复选框(checkbox)的操作汇总
2016/01/13 Javascript
谈一谈javascript中继承的多种方式
2016/02/19 Javascript
jQuery插件ajaxfileupload.js实现上传文件
2020/10/23 Javascript
vue2.0中click点击当前li实现动态切换class
2017/06/21 Javascript
手把手教你搭建ES6的开发运行环境
2017/07/11 Javascript
浅谈Vue SPA 首屏加载优化实践
2017/12/15 Javascript
详解webpack之scss和postcss-loader的配置
2018/01/09 Javascript
vue获取验证码倒计时组件
2019/08/26 Javascript
JS pushlet XMLAdapter适配器用法案例解析
2020/10/16 Javascript
Django框架下在URLconf中指定视图缓存的方法
2015/07/23 Python
python-pyinstaller、打包后获取路径的实例
2019/06/10 Python
Python文本处理简单易懂方法解析
2019/12/19 Python
flask 框架操作MySQL数据库简单示例
2020/02/02 Python
浅谈Python中的模块
2020/06/10 Python
CSS3地图动态实例代码(圆圈向外扩散)
2018/06/15 HTML / CSS
用纯CSS3实现网页中常见的小箭头
2017/10/16 HTML / CSS
工商治理实习生的自我评价分享
2014/02/20 职场文书
优秀实习生感言
2014/03/01 职场文书
优秀驾驶员先进事迹材料
2014/05/04 职场文书
高中学生自我评价范文
2014/09/23 职场文书
镇党政领导班子民主生活会思想汇报
2014/10/11 职场文书
社区文明创建工作总结2015
2015/04/21 职场文书
有关保护环境的宣传标语100条
2019/08/07 职场文书
导游词之神仙居景区
2019/11/15 职场文书
pandas求平均数和中位数的方法实例
2021/08/04 Python
ubuntu20.04虚拟机无法上网的问题及解决
2022/12/24 Servers