抛弃jQuery:Why?

我们需要理解jQuery背后的工作原理,掌握现代浏览器API,把Web开发从jQuery的陷阱中拯救出来,jQuery不等于JavaScript!

抛弃jQuery:Why?

原文链接:http://blog.garstasio.com/you-dont-need-jquery/

你不再需要jQuery!

现在的Web工程师太依赖jQuery了,某种意义上说jQuery已经成了JavaScript的同义词。但是我们真的需要他么?或许我们应该反思一下什么时候才真的需要jQuery。

对我个人而言开始使用jQuery的理由是他把我的工作变得简单多了,开发Web应用已经几乎离不开它。曾经在不同浏览器里Web API的实现有很大区别,而jQuery帮我抹平了这些,所以我很少再用document.getElementById这样的原生JavaScript 函数。依赖jQuery衍生出了无数极其优秀的类库,从完美的下拉菜单、复杂的表单验证到这几年流行的瀑布流布局,这些都让我的工作变得简单多了。

我一直坚信jQuery是开发JavaScript工程必须的,2012年,当时我需要开发维护一个跨浏览器的大文件上传组件时,我的第一直觉就是我要用jQuery重写已有的代码, 因为我已经下意识把jQuery当做简化工作的一部分标准。但是社区的用户并不希望我这样做——他们不想引入额外的第三方类库,就这样我(被迫/不情愿) 的重新开始学习原生浏览器API。出于意料的是,我发现不再依赖jQuery之后的工作比我想象的要简单得多!我曾经以为没有jQuery我就不会写 JavaScript代码了,但是现在我发现jQuery并不是必须的!

拐杖?陷阱?

曾几何时我第一次使用JavaScript开发大型项目,jQuery就同步进入了我的工作,事实上我是从见识了无比强大的jQuery选择符系统 之后才开始喜欢上Web开发的。我并没有深入学过“真正的”浏览器原生API(document.getElementById ?那时觉得看着好丑!),在被迫学习原生API之前,事实上我也不完全清楚怎么直接访问并操作DOM元素——jQuery全都帮我做了。jQuery已经 成了我的拐杖,当初用它是因为他能让我走的更好,但是后来我离开他已经不会走路了

我发现我掉进了一个陷阱,一个很多Web开发新手都掉进的陷阱。我本应该先花时间去理解JavaScript本身以及浏览器提供的API,但是我却因为jQuery提供的蜜罐而止步不前。逻辑上我们应该这样系统的学习JavaScript开发:

  1. 学习JavaScript语言
  2. 学习浏览器API
  3. 学习jQuery(或者其他框架、类库,实际项目中会大量用到的)

译者注:事实上这也是JavaScript的圣经犀牛书JavaScript: The Definitive Guide)的撰写顺序。可实际上包括译者在内,很多Web开发新手看到"第二部分:客户端Javascript"的时候就直接略过了,毕竟那时觉得和浏览器API比起来,jQuery看上去是那么优雅。

工程实践中,很多Web开发新手(比如我)是从第3步开始的,完全忽略了1和2的存在,这是完全可以理解的,因为学会了jQuery(或者其他类 库)我们就已经可以动手开始写代码了~ 但是如果你不清楚jQuery的背后到底发生了什么,就一定会在未来的开发中遇到问题。你也一定会遇到不能使用jQuery的项目,比如流行的 Angular.js这样的框架,初学者就最好删掉jQuery类库,从头开始学JavaScript。

跨浏览器支持

支持jQuery最常见的理由中最常见的一条,就是他修复了“不一致的DOM API”。这没错,但事实上不一致的DOM API只有在IE6/7及更早的版本中才大量存在。浏览器发展到2014年,非现代浏览器的使用比例已经越来越少。jQuery开发组自身也意识到这个问题,逐渐开始削减对这部分浏览器的支持,从jQuery 3.0开始,jQuery的版本分化支持所有浏览器的完整版只支持现代浏览器的精简版。我们需要面对的DOM API已经没有那么糟糕,基本的DOM元素创建、遍历和操作已经统一,至少在所有的现代浏览器中是这样。

从IE8开始,浏览器API开始逐渐标准、稳定,当然从细节上,IE10及早期的Safari/WebKit引擎中的某些实现确实不完全相同,但是 这些不同可以逐例分析,并且使用更小、更专用的类库来抹平。重点是:jQuery不是银弹,不能解决脚本中的所有跨浏览器问题,我们可以用更小、更专用且 可控的方式来抹平这些浏览器的差异。

JavaScript

另一个支持jQuery的常见理由是它弥补了一些JavaScript自身的缺陷,比如不方便的循环遍历、复杂的DOM访问等等。使用了第三方类库 (jQuery或Underscore等)之后,循环遍历变得比原来容易多了。这个理由曾经是正确的,但是现在JavaScript本身也在进 化,forEach、Object.keys()等函数的支持也很普遍了。曾经我很依赖$.inArray()函数,但是Array.prototype.indexOf()函数也早就是ECMA Script 5的一部分。类似的例子还有很多,后面我们可以在专题中慢慢探索。

需要马上抛弃jQuery么?

当然不是,如果jQuery使你的工作变得足够简单,如果你足够熟悉jQuery是如何工作的,接着使用jQuery没有一点儿问 题。这个系列的文 章是想告诉读者,我们可以使用原生的浏览器API完成需要的工作,而不需要引入庞大且不完全需要的类库。另外多了解jQuery本身是如何工作的总是没有 坏处。

译者注:

The better you understand what you are doing, the better you will do it.

对所做的事情理解越深,你就会做的越好。

——引自 The Singular Secret of the Rockstar Programmer / 编程巨星的唯一秘诀

 

 

抛弃jQuery:DOM API之选择元素

原文链接:http://blog.garstasio.com/you-dont-need-jquery/selectors/

DOM API 之选择元素

jQuery的选择符模块无比优雅,以至于我见过很多Web框架和应用中引用了庞大的jQuery,只是因为它提供了方便的DOM元素选择函数。我 已经数不清自己写过多少次 $(#myElement) 或者 $(‘.myElement‘) 了,以至于在没有jQuery时经常束手无策。事实上使用DOM API选择元素并没有那么难,它或许没有jQuery的那么简短,不过用起来也足够简单了。

ID

jQuery

// 返回一个jQuery对象
$(‘#myElement‘);

DOM API,我们最常见到的是这样:

// IE 5.5+
document.getElementById(‘myElement‘);

IE 8及以上版本的浏览器中可以使用querySelector函数:

// IE 8+
document.querySelector(‘#myElement‘);

这两种DOM API函数都直接返回一个元素,有测试表明getElementById函数比querySelector函数效率更高一些

随着浏览器升级,对querySelector函数的支持越来越好,jQuery的选择函数还有什么决定性的优势么?

CSS Classes

jQuery

// 返回所有匹配元素的jQuery对象
$(‘.myElement‘);

DOM API,IE 9及以上版本的浏览器中有专用的getElementsByClassName函数:

// IE 9+
document.getElementsByClassName(‘myElement‘);

IE 8及以上版本的浏览器中可以使用querySelectorAll函数:

// IE 8+
document.querySelectorAll(‘.myElement‘);

两种DOM API中getElementsByClassName的效率最高,返回一个HTMLCollection集合。后一种(querySelectorAll)返回NodeList类型。

jQuery能做到的,DOM API同样也做到了,不是么?

HTML 标签名

假设我们要选择所有的 div 元素:

jQuery

$(‘div‘);

DOM API,最常见的函数是这个:

// IE 5.5+
document.getElementsByTagName(‘div‘);

IE 8及以上版本的浏览器中依然可以使用querySelectorAll函数:

// IE 8+
document.querySelectorAll(‘div‘);

两种DOM API相比,getElementsByTagName的效率会稍微高一些。

HTML 属性

假设我们要选择 data-foo-bar 属性为 someval 的元素:

jQuery

$(‘[data-foo-bar="someval"]‘);

DOM API,IE 8及以上版本的浏览器中可以继续使用万能的querySelectorAll函数:

// IE 8+
document.querySelectorAll(‘[data-foo-bar="someval"]‘);

伪类

假设我们要从 id=myForm 的 from 元素中选择具备 :invalid 伪类的元素:

jQuery

$(‘#myForm :invalid‘);

DOM API,IE 8及以上版本的浏览器中可以继续使用万能的querySelectorAll函数:

// IE 8+
document.querySelectorAll(‘#myForm :invalid‘);

子元素

假设父元素id="myParent",如果我们只是想简单的选择所有子元素:

jQuery

$(‘#myParent‘).children();

DOM API,最熟悉的是这个:

// IE 5.5+
// NOTE: This will include comment and text nodes as well.
document.getElementById(‘myParent‘).childNodes;

IE 9及以上版本的浏览器中可以直接使用children来获取:

// IE 9+
// NOTE: This ignores comment & text nodes.
document.getElementById(‘myParent‘).children;

如果只是想获取包含 ng-click 属性的直接子元素呢?

jQuery

$(‘#myParent‘).children(‘[ng-click]‘);
// 或者
$(‘#myParent > [ng-click]‘);

DOM API,我是从这时开始发现querySelector比我想象的要强大…

// IE 8+
document.querySelector(‘#myParent > [ng-click]‘);

后代元素

假设祖先节点 id="myParent",我们希望获取其后代的所有超链接:

jQuery

$(‘#myParent A‘);

DOM API,IE 8及以上版本的浏览器里可以这样:

// IE 8+
document.querySelectorAll(‘#myParent A‘);

排除元素

假设我们要从 div 元素中获取出不带“ignore” class的元素

jQuery

$(‘DIV‘).not(‘.ignore‘);
// 或者
$(‘DIV:not(.ignore)‘);

DOM API,IE 8及以上版本的浏览器中可以这样:

// IE 9+
document.querySelectorAll(‘DIV:not(.ignore)‘);

多重选择

假设我们要选择所有的 div , a 和 script 元素:

jQuery

$(‘DIV, A, SCRIPT‘);

DOM API,IE 8及以上版本的浏览器里可以这样:

// IE 8+
document.querySelectorAll(‘DIV, A, SCRIPT‘);

仿造 jQuery 的 “$”

发现什么规律了么?

如果我们只考虑IE8及以上的浏览器,我们可以通过简单的代码“仿造”出类似jQuery中“$”选择符的效果:

window.$ = function(selector) {
  var selectorType = ‘querySelectorAll‘;

  if (selector.indexOf(‘#‘) === 0) {
      selectorType = ‘getElementById‘;
      selector = selector.substr(1, selector.length);
  }

  return document[selectorType](selector);
};

这段代码之后,你就可以在脚本中使用$来进行大部分选择元素的操作了。

可以替代 jQuery 的专用选择符模块

对于大部分JavaScript项目来说,原生的浏览器API已经足够进行DOM元素的选择了,但是我们也注意到,这些函数在低版本的IE浏览器中不能很好的工作。为了兼容低版本的浏览器,我们需要引入一些第三方的模块来帮助我们完成选择元素的任务。

当然直接引入jQuery是最直接的方法,但是我们如果我们只是为了享受选择元素的便利,那jQuery显然大材小用(浪费带宽)了。我们不妨试试Sizzle,这是一个很小的模块,专注于选择DOM元素,事实上jQuery正是使用了Sizzle作为它的一部分Selectivizr是另一个选择,同样很小,专注于在较早版本的浏览器中支持CSS3选择符,他同样被包含在jQuery, prototype, mootools等框架中。

抛弃jQuery:DOM API之操作元素

敬请期待 http://blog.cabbit.me/you-dont-need-jquery/

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。