jQuery是现在最流行的JavaScript工具库。
据统计,目前全世界57.3%的网站使用它。也就是说,10个网站里面,有6个使用jQuery。如果只考察使用工具库的网站,这个比例就会上升到惊人的91.7%。
虽然jQuery如此受欢迎,但是它臃肿的体积也让人头痛不已。jQuery 2.0的原始大小为235KB,优化后为81KB;如果是支持IE6、7、8的jQuery 1.8.3,原始大小为261KB,优化后为91KB。
这样的体积,即使是宽带环境,完全加载也需要1秒或更长,更不要说移动设备了。这意味着,如果你使用了jQuery,用户至少延迟1秒,才能看到网页效果。考虑到本质上,jQuery只是一个操作DOM的工具,我们不仅要问:如果只是为了几个网页特效,是否有必要动用这么大的库?
2006年,jQuery诞生的时候,主要用于消除不同浏览器的差异(主要是IE6),为开发者提供一个简洁的统一接口。相比当时,如今的情况已经发生了很大的变化。IE的市场份额不断下降,以ECMAScript为基础的JavaScript标准语法,正得到越来越广泛的支持。开发者直接使用JavScript标准语法,就能同时在各大浏览器运行,不再需要通过jQuery获取兼容性。
下面就探讨如何用JavaScript标准语法,取代jQuery的一些主要功能,做到jQuery-free。
一、选取DOM元素
jQuery的核心是通过各种选择器,选中DOM元素,可以用querySelectorAll方法模拟这个功能。
var $ = document.querySelectorAll.bind(document);
这里需要注意的是,querySelectorAll方法返回的是NodeList对象,它很像数组(有数字索引和length属性),但不是数组,不能使用pop、push等数组特有方法。如果有需要,可以考虑将Nodelist对象转为数组。
myList = Array.prototype.slice.call(myNodeList);
二、DOM操作
DOM本身就具有很丰富的操作方法,可以取代jQuery提供的操作方法。
尾部追加DOM元素。
// jQuery写法
$(parent).append($(child));// DOM写法
parent.appendChild(child)
头部插入DOM元素。
// jQuery写法
$(parent).prepend($(child));// DOM写法
parent.insertBefore(child, parent.childNodes[0])
删除DOM元素。
// jQuery写法
$(child).remove()// DOM写法
child.parentNode.removeChild(child)
三、事件的监听
jQuery的on方法,完全可以用addEventListener模拟。
Element.prototype.on = Element.prototype.addEventListener;
为了使用方便,可以在NodeList对象上也部署这个方法。
NodeList.prototype.on = function (event, fn) {
[]['forEach'].call(this, function (el) {
el.on(event, fn);
});
return this;
};
四、事件的触发
jQuery的trigger方法则需要单独部署,相对复杂一些。
Element.prototype.trigger = function (type, data) {
var event = document.createEvent('HTMLEvents');
event.initEvent(type, true, true);
event.data = data || {};
event.eventName = type;
event.target = this;
this.dispatchEvent(event);
return this;
};
在NodeList对象上也部署这个方法。
NodeList.prototype.trigger = function (event) {
[]['forEach'].call(this, function (el) {
el['trigger'](event);
});
return this;
};
五、document.ready
目前的最佳实践,是将JavaScript脚本文件都放在页面底部加载。这样的话,其实document.ready方法(jQuery简写为$(function))已经不必要了,因为等到运行的时候,DOM对象已经生成了。
六、attr方法
jQuery使用attr方法,读写网页元素的属性。
$("#picture").attr("src", "http://url/to/image");
DOM元素允许直接读取属性值,写法要简洁许多。
$("#picture").src = "http://url/to/image";
需要注意,input元素的this.value返回的是输入框中的值,链接元素的this.href返回的是绝对URL。如果需要用到这两个网页元素的属性准确值,可以用this.getAttribute('value')和this.getAttibute('href')。
七、addClass方法
jQuery的addClass方法,用于为DOM元素添加一个class。
$('body').addClass('hasJS');
DOM元素本身有一个可读写的className属性,可以用来操作class。
document.body.className = 'hasJS';
// or
document.body.className += ' hasJS';
HTML 5还提供一个classList对象,功能更强大(IE 9不支持)。
document.body.classList.add('hasJS');
document.body.classList.remove('hasJS');
document.body.classList.toggle('hasJS');
document.body.classList.contains('hasJS');
八、CSS
jQuery的css方法,用来设置网页元素的样式。
$(node).css( "color", "red" );
DOM元素有一个style属性,可以直接操作。
element.style.color = "red";;
// or
element.style.cssText += 'color:red';
九、数据储存
jQuery对象可以储存数据。
$("body").data("foo", 52);
HTML 5有一个dataset对象,也有类似的功能(IE 10不支持),不过只能保存字符串。
element.dataset.user = JSON.stringify(user);
element.dataset.score = score;
十、Ajax
jQuery的Ajax方法,用于异步操作。
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
我们可以定义一个request函数,模拟Ajax方法。
function request(type, url, opts, callback) {
var xhr = new XMLHttpRequest();
if (typeof opts === 'function') {
callback = opts;
opts = null;
}xhr.open(type, url);
var fd = new FormData();
if (type === 'POST' && opts) {
for (var key in opts) {
fd.append(key, JSON.stringify(opts[key]));
}
}xhr.onload = function () {
callback(JSON.parse(xhr.response));
};xhr.send(opts ? fd : null);
}
然后,基于request函数,模拟jQuery的get和post方法。
var get = request.bind(this, 'GET');
var post = request.bind(this, 'POST');
十一、动画
jQuery的animate方法,用于生成动画效果。
$foo.animate('slow', { x: '+=10px' });
jQuery的动画效果,很大部分基于DOM。但是目前,CSS 3的动画远比DOM强大,所以可以把动画效果写进CSS,然后通过操作DOM元素的class,来展示动画。
foo.classList.add('animate');
如果需要对动画使用回调函数,CSS 3也定义了相应的事件。
el.addEventListener("webkitTransitionEnd", transitionEnded);
el.addEventListener("transitionend", transitionEnded);
十二、替代方案
由于jQuery体积过大,替代方案层出不穷。
其中,最有名的是zepto.js。它的设计目标是以最小的体积,做到最大兼容jQuery的API。zepto.js 1.0版的原始大小是55KB,优化后是29KB,gzip压缩后为10KB。
如果不求最大兼容,只希望模拟jQuery的基本功能,那么,min.js优化后只有200字节,而dolla优化后是1.7KB。
此外,jQuery本身采用模块设计,可以只选择使用自己需要的模块。具体做法参见它的github网站,或者使用专用的Web界面。
十三、参考链接
- Remy Sharp,I know jQuery. Now what?
- Hemanth.HM,Power of Vanilla JS
- Burke Holland,5 Things You Should Stop Doing With jQuery
(完)
riophae 说:
这篇文章适合那些从 jQuery 入门 JavaScript 的同学学习啊.
2013年5月11日 20:20 | # | 引用
kmxz 说:
写了很多年JS,基本都在写vanilla JS。用过Google closure library,用过angular.js,从来不用jQuery。
对jQuery及其厌恶,无非就是少量syntactic sugar,把代码变得更不优雅且带来各种overhead。
2013年5月11日 20:26 | # | 引用
陈玉驰 说:
jQuery的优化缩减支持IE低版本,也说明了标准化的趋势,只是国内的银行、大型国企还在使用IE6...
2013年5月11日 20:27 | # | 引用
倉優小子 说:
jquery在删除dom元素前对元素上的已绑定的事件做了清理操作,防止内存泄漏,在用原生js操作dom时也应该注意这一点。
2013年5月11日 20:42 | # | 引用
匿名选手 说:
博主,非常感谢你的这篇文章,这是我从没想过的事,当然我也刚入门。
不过我有一些问题想请教你,能说说你是如何开始构思一篇文章的吗,是如何发现这个思路,然后花了多长时间写文章,这些时间是如何安排出来的,你是同时构思几篇文章,还是一篇写完后才开启第二篇?你可以考虑写篇文章介绍下,相信对其他人也有用的。因为你发文章的速度比我快多了,我经常忙的忘了我还开了博客这件事,所以有这些疑问。
先行道谢了。
2013年5月11日 22:30 | # | 引用
Pride Chung 说:
好讽刺,jQuery当初干掉其他JS libraries 很重要的一个原因就是小巧的体积,1.3版貌似只有30K出头。
2013年5月11日 23:14 | # | 引用
Jak Wings 说:
看来 jQuery 终有一天会被淘汰,抑或说 jQuery 也会像 Zepto 那样精简化。jQuery 的语法糖还是设计得很不错的,现在改用 Zepto 也不错。
2013年5月12日 07:37 | # | 引用
Jak Wings 说:
去 Zepto 的 GitHub 看了下源码,发现 $.fn.detach 功能还没弄好,暂时用 $.fn.remove 替代着。
2013年5月12日 07:44 | # | 引用
墨菲斯托同学 说:
jquery的确很大,但是另外一个情况是,大部分网站都加载jquery,在第一次以后jquery就存在用户电脑中了,下次直接调用本地的jquery库。
所以并不是每次加载含有jquery的网页都会延迟一秒钟。
如果用户浏览得越多网页,平均下来加载的延迟就会越低。
比起js来说,jquery在开发上还是简单容易许多的
2013年5月12日 08:22 | # | 引用
olyd 说:
软老师可否写一些关于linux内核方面的文章啊。不打算写本书吗?
2013年5月12日 10:41 | # | 引用
laoguo 说:
从一开始就不用jQuery的话还可以铁下心来,无视那些丰富美妙的jQuery plugin,通过实践jQuery-free来成长为一个独行大侠。可一旦已经用上了jQuery,恐怕就不可能不用了。
2013年5月12日 12:31 | # | 引用
greatghoul 说:
这个前提应该是使用了 CDN
2013年5月12日 15:22 | # | 引用
Gao Jie 说:
使用公用的jquery cdn链接,是解决这个库文件偏大的更优解。既然已有的网站都有超过50%使用jquery,而且普通用户接触到的大型网站比如微博,淘宝, 都提供了静态的cdn给jquery使用(google,微软也有)。那么自己的小网站在include js文件的时候如果是使用这些cdn,一方面网速很快,延迟小, 另外一方面,这个链接极大可能已经被用户的浏览器缓存了,所以实际上不会花费任何网络流量和延时。
2013年5月12日 19:43 | # | 引用
红色石头 说:
jquery无法被替代,文章名字应该改成《JQuery和原生JS操作的10个区别》
已转载~
2013年5月13日 09:44 | # | 引用
Tux 说:
写的很好!很简单的网页也用jquery确实太重量了。
发现这个网站引用了你的文章:
http://blog.jobbole.com/39546
但是中间插入了很多广告(e.g 什么教育网),这可能不符合你声明的“Creative Commons BY-NC-ND 3.0”协议。
2013年5月13日 10:43 | # | 引用
黄利民 说:
To @ruanyf:从其他网站复制了内容,没有删除干净那个网站强行添加的内容,这是我们的失误,十分抱歉。我们已删除更新了。
谢谢Tux的提醒。
2013年5月13日 12:04 | # | 引用
murusu 说:
jquery的加载问题可以通过cdn来解决
用原生js虽然速度快,可是会带来两个问题:
一个是代码量的增多,二是无法利用现有的jquery plugin,
这两点所导致的开发流程延长足够抵消使用原生js的速度优势
2013年5月13日 12:33 | # | 引用
风海迷沙 说:
已经使用了CDN无压力,包括jquery-ui
2013年5月13日 12:35 | # | 引用
bachue 说:
减少体积这种事情和优化性能一样都是一条不归路啊
只要没有明显的性能问题,何必去干这个?
jQuery明显成熟而且功能强大,如果其他库没有拿出更好的功能,仅仅精简代码,那就毫无疑义了。
网速问题最终会被时间解决,庞大的人力物力下去就是为了精简功能,甚至使用一个不成熟的库,有意思吗?
我以前也想过类似的事情,现在都发现毫无意义了,太蛋疼了。
2013年5月13日 14:01 | # | 引用
摸摸来了 说:
感觉各有千秋吧。。
2013年5月13日 14:21 | # | 引用
小牛仔 说:
这个和cdn有什么关系,这个应该是web服务器设置了缓存头信息就可以。
2013年5月14日 13:24 | # | 引用
rambo 说:
我非常同意此观点 中小型公司追求的就是效率 高效 中小公司往往在高人才上面比较缺乏,如果上来就让一个前端工程师用原生js 也许速度什么的是高了 但是老板不乐意啊 他们追求的更多的是 RMB 啊
如今的网速(pc:目前查看普遍都是4M网速 手机端:3G 4G wifi) 缓存 用户浏览器的提高(ff chrome ie10份额提升) 加上许多公司开始放弃自己的jquery使用大公司的CDN 楼主如果仅仅是因为大小的问题,则完全可以忽视.
ps:
网传比较好的方法(因避免html标签解析错误 使用中文代替):
使用google CDN:
http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js
然后检测是否加载完毕 (网速 或者 被墙之类的)
if(!jQuery){document.write('你自己的src')}
2013年5月16日 18:27 | # | 引用
Rache 说:
深深感觉银行他们严重影响开发人员进步……
2013年5月25日 21:38 | # | 引用
inhu.net 说:
这个做法很久之前看到过..不过我觉得满足不了我强大的需求
2013年5月29日 15:48 | # | 引用
欧文 说:
首张那图片是什么书,好像不是英文版的。难道峰哥还会其它什么语言的?膜拜中...
2013年5月30日 09:16 | # | 引用
依云 说:
德文。
今天在自己的 reveal.js 修改中做到了 jQuery free,哦耶~
2013年5月30日 19:11 | # | 引用
qinshou.me 说:
…求返回页首按钮
2013年6月 7日 10:51 | # | 引用
ph1t 说:
同求增加返回页首。。
2013年6月28日 23:58 | # | 引用
V客小站 说:
试用了一下Zepto,发现其他使用了jQuery的库无法正常工作,放弃!
2013年8月 4日 07:43 | # | 引用
宁逍遥 说:
并非所有的浏览器都有效兼容css3, 为了加快一秒中的加载速度, 愿意抛弃那些用户和开发效率, 也可以放弃jQuery. 随着网速和硬件水平的不断提高, 所有的性能问题都不是问题. 而且我认为用户并不像我们认为的那么急不可待.
2013年8月20日 14:54 | # | 引用
星空 说:
看了一下zepto.js 发现官网没打算支持 IE
2013年8月21日 16:28 | # | 引用
张钦青 说:
我也主张如果几个简单的小效果还用jQ就太重了。问题是楼主以上列举的几个方法貌似对IE6的支持性不好。。
2013年10月18日 12:58 | # | 引用
新浪微博rss 说:
jQuery很赞,特别是对现代浏览器,对于IE,那就没有办法了。
2013年10月25日 14:15 | # | 引用
随便说两句 说:
当然有关系。因为前面大家说的CDN,不是自己域名的CDN,而是ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js这种类型的CDN。这种CDN使用的网站非常多,一个用户访问的某一个网站使用了这个CDN,你的页面再加载时,就不用再次加载了,体积大小也就不是问题了。
这篇文章我是不大赞同的。虽然JQuery体积确实大,但是其带来的开发便利性,对于中小型团队来说是非常重要的。毕竟中小型团队没有Yahoo,淘宝,Twitter这种公司那么强大的实力,自己搞一套好用的框架出来是相当不现实的。
因为体积原因而放弃JQuery,就像因为性能原因只使用C语言,放弃Java,C#,甚至C++一样
2013年10月31日 11:11 | # | 引用
digdeep126 说:
2013年11月23日 21:48 | # | 引用
新一 说:
看团队能力吧,个人想法普通的小团队也包括我的,用jquery会比较妥当。
2013年12月29日 11:24 | # | 引用
Mayon 说:
其实jquery没那么可恶,对于敏捷开发而言,利于整个团队的开发进度。不过,如果个人想在前端领域更进一步,自然需要摒弃对jquery的依赖。其实,当年我开始自学前端时,听都没听说过jquery,哈哈,还是换了一家公司之后才被要求用jquery。不过如今想起来,还真是庆幸当年傻了叭唧的只知道埋头学自己的。
2014年3月 4日 11:42 | # | 引用
zjzhome 说:
好文。不过还没用过jQuery,用了下zepto,发现这个东西确实是方便,但是会导致像我这样的入门者基础不牢。
2014年5月21日 18:50 | # | 引用
MR.陈 说:
拿到手机上就知道jQuery真的是不行!!
2014年5月29日 12:17 | # | 引用
lxjwlt 说:
开发中 必须用到代码库的 不管是jQuery 还是其他的库 直接用原生代码来开发 还是得写成一个库嘛 不然冗余代码多 维护性差
只是jQuery作为一个给大家用的库 要考虑的东西非常的多 所以代码量大是必然的
2014年6月14日 17:58 | # | 引用
JS 说:
只用原生JS不用框架的路过。
2014年8月11日 01:57 | # | 引用
初学者 说:
如果你们去开发移动端, 就会发现, 性能开销是个多么重要的问题.
自从转移动端WEB开发之后, 基本没用过任何库了, 全部原生Js.
原生js操作dom, 也并非我最开始想的那么棘手, 反而让我对jQuery的一些机制更加明白了.
特效用css3.
基本和博主建议的差不多.
2015年6月 1日 17:40 | # | 引用
怠惰之熊 说:
移动端有个好处就是环境极其统一,而且支持各种最新的特性,因为andriod和iOS的浏览器都是webkit,这样用原生JS写起来基本不需要多少兼容性处理。web版的firefox和WP的浏览器虽然内核不同,但好歹都是支持了新标准的,而且占比不高。而且移动端窘迫的性能和带宽也跟适合使用原生JS。
然而到了PC端,各种浏览器新旧版本并存,运行环境五花八门,除非你下定决心只支持最新浏览器,否则各种兼容性问题层出不穷。不过PC拥有更高的性能和更快的带宽,配合CDN的话,jQuery的大小并不是什么问题。
从个人学习的角度来看,脱离jQuery是必要的,但是从项目开发的角度来看,jQuery能让开发人员更专心于业务逻辑的实现。
2015年6月 8日 14:54 | # | 引用
杯子里的影子 说:
其实我是挺喜欢JQuery的,而且觉得现在的网络环境下一个JQuery库大概也不算什么。脱离不脱离JQuery其实对JavaScript本身的水平影响不大吧?不过可能会更加清楚DOM的那些东西。
CSS3动画据说有硬件加速,然而前一阵子(大概一两年前?)不知道为什么性能还是很差,尤其是移动端,非常差,现在不知道怎么样了。DOM动画的话,有个小问题需要注意是,要发生动画的元素得拿出来,别让整个DOM陪它重绘去……
最近经常用Typescript+Angular1.x,虽然没有什么因果关系,但是微妙的发现自己好像不怎么用JQuery了。
2015年6月 9日 15:58 | # | 引用
andy 说:
请问阮老师NodeList.prototype.on这个肿么使用,没看懂。。
2016年2月23日 10:08 | # | 引用
朽木 说:
还有各种医院...
2016年3月 3日 15:16 | # | 引用
Double 说:
怎么就用其他框架就用出优越感,极其厌恶了,只能显示自己是个lowB
2016年3月18日 16:32 | # | 引用
BF200 说:
jquery无法被替代,文章名字应该改成《JQuery和原生JS操作的10个区别》
2016年5月28日 11:42 | # | 引用
eeee 说:
兼容问题怎么办?不能一味的否定jQuery
2016年7月19日 20:08 | # | 引用
weaming 说:
文章开头就写了。。
2016年7月25日 21:00 | # | 引用
歌小熊 说:
这才过了几年啊,我们连dom都不用操作了,喵哈哈哈哈哈
2016年9月 2日 14:51 | # | 引用
NsZbf 说:
现在变化太快了,ng2 react.js webpack gulp....,已经让人措手不及了
2016年9月29日 10:18 | # | 引用
嘻嘻白 说:
没有返回按钮确实不方便,只能自己动手写一个,扩展了。。。
2016年11月23日 13:55 | # | 引用
dante 说:
真是要用发展的眼光看问题啊,前几楼说jQuery无法被替代的应该没想到过了没几年出来了angular,react,vue等前端框架。。已经颠覆了前端的写码方式
2016年12月 9日 10:16 | # | 引用