之所以说要摆脱jquery,并不是说jquery不好用,本人也是佩服jquery五体投地,在没有用上jquery的时候我还没认识到javascript如此强大的功能,好在jquery的脚本是全部开源的,在它的里面我们能够学到很多的东西。不过我看过它的源码,可能是由于本人的js水平有限还有很多地方看不是很明白,不过在使用的过程可以得知jquery之所以如此强大得意于的它封装的dom对象类,并且几乎提供一个几乎"万能"的筛选器,而封装类又提供很多方便常见的方法操作dom对象,最重要的一点是jquery帮我兼容搞定所有的浏览器,使得我们不需要再考虑为ff、opera或safari做单独的判断,所以jquery倍受程序员的青睐。jquery还能进行很好扩展,提供了很多丰富的插件,也有提供一整套UI解决方案,还算好用啦。不过可能是由于本人比较叛逆的性格,出与没事干找抽,呵呵,就是不想再用jquery,也没有啦,下面我来说一下我为什么不再想用jquery的原因:
- jquery脚本文件较庞大,1.2.6版没打包前有98kb,而打包后也占了31kb,但我们通常只用它其中的一个很小部分功能,感觉就有点浪费,所以没有必要把这么大的一个jquery脚本文件引用到页面;
- 本身的一些Bug,无论写什么东西都可能会有bug,虽然jquery是开源的,但是一般很少有人能真正看懂它里面的框架而进行修正。bug如放入了jquery脚本自定义的window的resize事件不能正确触发,UI里面的滚动页面后的拖拽bug(好象新版已修复),及和其他脚本库不能兼容等。
- 不能满足所有的需求,这点是必然的,jquery只能做到尽量通用。对于那些门户网站我想它一定不会要依赖jquery,而是会积累出来一套适合自己的脚本库,如ajax。我想要ajax在callback回调函数不止带responseText还需要自定义多传一个参数,jquery没有提供那只能自己写。
- 有时候直接操作dom对象会比jquery更直接方便,如document.getElementById('test').innerHTML += 'html'而jquery要使用$('#test').html( $('#test').html()+'html' ),有人会说那上面我写的代码还是比jquery的长,但是其实我们在js里面用到document.getElementById并不是很多,最重要的还是一些逻辑判断操作。这里再暴jquery一个小bug:不知它做了什么判断使用$("#test").html(0)后test的innerHTML被设成了''空而不是0,但使用最原始的东西当然是不会有错的。
说了这么多无非就是想不用jquery,那么我们应该使用什么东西来代替jquery里面的一些常见方法呢,还有什么?DIY(Do it yourself)自己来写呗~~
首先,我们需要的是一个类似于jquery的筛选器函数,并且返回的是数组,能像jquery一样批量的操作dom元素,这里我暂时不想用jquery那样自己做个对象来封装dom元素,先直接就用个Array好了,筛选器函数代码如下:
{
if ( typeof(selector) != 'string' ) return selector;
var selectors = selector.trim().split(' '), list = new Array();
list.push(document);
//debugger;
for (var i=0; i<selectors.length; i++)
{
var item = selectors[i];
if (item.trim()=='' ) continue;
//if (item.indexOf('#') > -1 )
//{
// list.length = 1;
// var id = item.substring(1,item.search(/\.|\[/));
// if (id.trim()!='') list.push(document.getElementById(id));
//}else
//{
//上次列表
var tmp = list.slice(0), doc = tmp.length > 0 ? tmp[0] : document;
list.length = 0;//重置
//var tmpList = new Array();
for(var j=0; j<tmp.length; j++)//循环上次列表
{
var tagName = item.search(/\.|\[/) > -1 ? item.substring(0,item.search(/\.|\[/)) : item;
if (tagName.trim()=='') tagName='*';
var tmpList = doc.getElementsByTagName( tagName );
for(var tl=0; tl<tmpList.length; tl++ ) { list.push(tmpList[tl]); }
var className = item.indexOf('.') > -1 ? item.substring( item.indexOf('.'), item.indexOf('[') ) : '';
var attrlist = item.match(/\[\S+=\S+\]/g);
if (className.trim()!='' || attrlist!=null)
{
for(var t=0; t<list.length; t++)
{
if(className.trim()!='' && list[t].className!=className.trim()) list.splice(t,1);
if (attrlist!=null && attrlist.length > 0)
{
for(var a=0; a<attrlist.length; a++)
{
var attr = attrlist[a].trim().split('='), name = attr[0].substring(1), val = attr[1].substring(0,attr[1].length-1);
if (list[t].getAttribute && list[t].getAttribute(name) != val) list.splice(t,1);
}
}
}
}
//if (tmp.length > 0) list = list.concat( tmp );
doc = tmp[tmp.length>=2?j+1:j];
}
//}
//if (i==selectors.length-1)
//{
// list.shift();return list;
//}
//alert(item);
}
//list.shift();
return list;
}
String.prototype.trim= function() { return this.replace(/(^\s*)|(\s*$)/g, ""); };
以上是实现类似jquery筛选的方法,还有为#id等的情况没有考虑,支持加tagName $$('div'),再加类筛选 $$('div.className'),加属性值$$('div[title=main]'),以空格间隔的dom层次$$('div p li')的筛选,返回为Array数组,那么我们操作筛选后的元素只需要扩展Array的prototype如下所示:
Array.prototype.drag = function (){
for(var i=0; i<this.length;i++)
{
function eDrag(target,e)
{
target.style.position = 'absolute';
var e = window.event || e;
var _xy = parseInt(target.offsetTop) - e.clientY;
var _xx = parseInt(target.offsetLeft) - e.clientX;
document.onmouseup = function(){
this.onmousemove = null;
}
if(e.preventDefault){
e.preventDefault();
}
document.onmousemove = function(e){
var e = window.event || e;
target.style.top = _xy + e.clientY + "px";
target.style.left = _xx + e.clientX + "px";
}
}
this[i].onmousedown = function (e){ eDrag(this,e);};
}
};
上面只对Array的css和drag进行扩展,我这里只是示范下,以后我们还可以从jquery那里偷过来一些方法到这里来进行扩展,我们先来试一下drag拖拽的功能。
html元素结构如下:
今天就先写到这里,下次续。。。