使用原生js替换jQuery

使用原生js替换jQuery

jQuery是现在最流行的JavaScript工具库。

统计,目前全世界57.3%的网站使用它。也就是说,10个网站里面,有6个使用jQuery。如果只考察使用工具库的网站,这个比例就会上升到惊人的91.7%。

bg2013051101

虽然jQuery如此受欢迎,但是它臃肿的体积也让人头痛不已。jQuery 2.0的原始大小为235KB,优化后为81KB;如果是支持IE6、7、8的jQuery 1.8.3,原始大小为261KB,优化后为91KB。

这样的体积,即使是宽带环境,完全加载也需要1秒或更长,更不要说移动设备了。这意味着,如果你使用了jQuery,用户至少延迟1秒,才能看到网页效果。考虑到本质上,jQuery只是一个操作DOM的工具,我们不仅要问:如果只是为了几个网页特效,是否有必要动用这么大的库?

bg2013051102

2006年,jQuery诞生的时候,主要用于消除不同浏览器的差异(主要是IE6),为开发者提供一个简洁的统一接口。相比当时,如今的情况已经发生了很大的变化。IE的市场份额不断下降,以ECMAScript为基础的JavaScript标准语法,正得到越来越广泛的支持。开发者直接使用JavScript标准语法,就能同时在各大浏览器运行,不再需要通过jQuery获取兼容性。

下面就探讨如何用JavaScript标准语法,取代jQuery的一些主要功能,做到jQuery-free。

bg2013051103

一、选取DOM元素

jQuery的核心是通过各种选择器,选中DOM元素,可以用querySelectorAll方法模拟这个功能。

  var = document.querySelectorAll.bind(document);</p></blockquote><p>这里需要注意的是,querySelectorAll方法返回的是NodeList对象,它很像数组(有数字索引和length属性),但不是数组,不能使用pop、push等数组特有方法。如果有需要,可以考虑将Nodelist对象转为数组。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  myList = Array.prototype.slice.call(myNodeList);</p></blockquote><p><strong>二、DOM操作</strong></p><p>DOM本身就具有很丰富的操作方法,可以取代jQuery提供的操作方法。</p><p>尾部追加DOM元素。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  // jQuery写法<br>(parent).append((child));</p><p>// DOM写法<br> parent.appendChild(child)</p></blockquote><p>头部插入DOM元素。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  // jQuery写法<br>(parent).prepend((child));</p><p>// DOM写法<br> parent.insertBefore(child, parent.childNodes[0])</p></blockquote><p>删除DOM元素。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  // jQuery写法<br>(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’;
});
return this;
};

五、document.ready

目前的最佳实践,是将JavaScript脚本文件都放在页面底部加载。这样的话,其实document.ready方法(jQuery简写为(function))已经不必要了,因为等到运行的时候,DOM对象已经生成了。</p><p><strong>六、attr方法</strong></p><p>jQuery使用attr方法,读写网页元素的属性。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>(“#picture”).attr(“src”, “http://url/to/image“);

DOM元素允许直接读取属性值,写法要简洁许多。

  ("#picture").src = "http://url/to/image";</p></blockquote><p>需要注意,input元素的this.value返回的是输入框中的值,链接元素的this.href返回的是绝对URL。如果需要用到这两个网页元素的属性准确值,可以用this.getAttribute('value')和this.getAttibute('href')。</p><p><strong>七、addClass方法</strong></p><p>jQuery的addClass方法,用于为DOM元素添加一个class。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>(‘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" );</p></blockquote><p>DOM元素有一个style属性,可以直接操作。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  element.style.color = "red";;</p><p>// or</p><p>element.style.cssText += 'color:red';</p></blockquote><p><strong>九、数据储存</strong></p><p>jQuery对象可以储存数据。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>(“body”).data(“foo”, 52);

HTML 5有一个dataset对象,也有类似的功能(IE 10不支持),不过只能保存字符串。

  element.dataset.user = JSON.stringify(user);

element.dataset.score = score;

十、ajax

jQuery的Ajax方法,用于异步操作。

  .ajax({<br> type: "POST",<br> url: "some.php",<br> data: { name: "John", location: "Boston" }<br> }).done(function( msg ) {<br> alert( "Data Saved: " + msg );<br> });</p></blockquote><p>我们可以定义一个request函数,模拟Ajax方法。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  function request(type, url, opts, callback) {</p><p>var xhr = new XMLHttpRequest();</p><p>if (typeof opts === 'function') {<br> callback = opts;<br> opts = null;<br> }</p><p>xhr.open(type, url);</p><p>var fd = new FormData();</p><p>if (type === 'POST' &amp;&amp; opts) {<br> for (var key in opts) {<br> fd.append(key, JSON.stringify(opts[key]));<br> }<br> }</p><p>xhr.onload = function () {<br> callback(JSON.parse(xhr.response));<br> };</p><p>xhr.send(opts ? fd : null);</p><p>}</p></blockquote><p>然后,基于request函数,模拟jQuery的get和post方法。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>  var get = request.bind(this, 'GET');</p><p>var post = request.bind(this, 'POST');</p></blockquote><p><strong>十一、动画</strong></p><p>jQuery的animate方法,用于生成动画效果。</p><blockquote style="font: 12px/21.6px Consolas, Monaco, 'Andale Mono', monospace; margin: 2em; padding: 1em; border-radius: 1em; border: 0.3em solid #e0dfcc; text-align: left; color: #111111; text-transform: none; text-indent: 0px; letter-spacing: -0.12px; overflow: auto; text-decoration: none; word-spacing: 2.4px; list-style-type: none; white-space: normal; widows: 1; font-size-adjust: none; font-stretch: normal; background-color: #f5f2f0; text-shadow: white 0px 1px; -webkit-text-stroke-width: 0px;"><p>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

(完)

原文来自:如何做到 jQuery-free?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值