jQuery到javascript的参考 - 帮助你了解javascript底层
日期:2012/01/25 来源:GBin1.com
越来越多的开发人员都先接触jQuery而非javascript。很多情况下,对于新手都很幸运。 他们使用很多新的javascript类库,帮助他们快速简单的处理DOM,但是很不幸,他们都不是真正了解这些API。
在本文中,我们将介绍一些常用的jQuery应用,并且将他们转化成现代和遗留的javascript。
开始之前
注意我们使用的一些遗留代码例子将使用简单的跨浏览器的addEvent方法。这个方法保证所有的W3C推荐的事件模型,addEventListener和IE的遗留attachEvent都正常执行。
所以,当我们参考addEvent(els,event,handler)时,参考下面方法:
var addEvent = (function () {
var filter = function(el, type, fn) {
for ( var i = 0, len = el.length; i < len; i++ ) {
addEvent(el[i], type, fn);
}
};
if ( document.addEventListener ) {
return function (el, type, fn) {
if ( el && el.nodeName || el === window ) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
filter(el, type, fn);
}
};
}
return function (el, type, fn) {
if ( el && el.nodeName || el === window ) {
el.attachEvent('on' + type, function () { return fn.call(el, window.event); });
} else if ( el && el.length ) {
filter(el, type, fn);
}
};
})();
// usage
addEvent( document.getElementsByTagName('a'), 'click', fn);1. $('#container');
这个方法调用将会查询DOM中一个id为container的元素,并且创建一个新的jQuery对象。
现代浏览器JS
var container = document.querySelector('#container');querySelectors是选择器API的一个部分,提供我们通过CSS查询DOM的能力
这个特定方法返回第一个匹配传递选择器的元素
传统遗留代码
var container = document.getElementById('container'); 注意你是如何参考元素的。当使用getElementById,你将单独传递一个值,然而使用querySelector,则需要一个CSS选择器
2. $('#container').find('li');
这次我们不单单找一个元素,我们需要查找所有#container的子元素。
现代浏览器
var list = document.querySelectorAll('#container li'); querySelectorAPI返回所有的符合指定CSS选择器的元素
selector限制 :虽然所有的相关的浏览器都支持Selector API,你传递的指定CSS选择器还是受限于浏览器,IE8只支持CSS2.1选择器。
传统遗留代码
var list = document.getElementById('container').getElementsByTagName('li'); 3 – $('a').on('click', fn);
在这里例子中,我们将添加一个click事件到所有的anchor标签
现代浏览器
[].forEach.call( document.querySelectorAll('a'), function(el) {
// anchor was clicked
}); 以上代码看起来比较恐怖,但是不是很差。因为querySelectorAll返回了一个静态的NodeList而不是一个数组,我们无法直接访问访问,如,foreach。但这个可以被通过调用forEach来弥补,通过作为this来传递querySelectorAll的结果。
传统遗留代码
var anchors = document.getElementsbyTagName('a');
addEvent(anchors, 'click', fn); 4 – $('ul').on('click', 'a', fn);
这个例子稍有不同。这一次,我们使用event delegation。click监听将会被应用到无序的列表中。然而,callback功能将只会在目标为anchor标签时才调用。
现代浏览器
document.addEventListener('click', function(e) {
if ( e.target.matchesSelector('ul a') ) {
// proceed
}
}, false); 技术上来讲,这个JS方法和上面jQUery的不同,它将事件监听直接添加到了document。使用新的matchesSelector方法来判断是否目标结点被点击。这个方法我们添加了一个单一的事件监听,而不是很多
请注意,当我们撰写这个文章的时候,所有的浏览器通过他们自己的各自的后缀来执行了matchesSelector:mozMatchesSelector,webkitMatchesSelector。为了统一代码,我们执行如下:
var matches;
(function(doc) {
matches =
doc.matchesSelector ||
doc.webkitMatchesSelector ||
doc.mozMatchesSelector ||
doc.oMatchesSelector ||
doc.msMatchesSelector;
})(document.documentElement);
document.addEventListener('click', function(e) {
if ( matches.call( e.target, 'ul a') ) {
// proceed
}
}, false);
使用以上代码,在webkit内核浏览器中,会参考 webkitMatchesSelector,而在mozilla,则使用mozMatchesSelector
传统遗留代码
var uls = document.getElementsByTagName('ul');
addEvent(uls, 'click', function() {
var target = e.target || e.srcElement;
if ( target && target.nodeName === 'A' ) {
// proceed
}
}); 我们判断是否nodeName属性等于我们需要的查询。特别注意老版本的IE浏览器有时候使用自己的规则。你不能够直接从event访问target,你需要查看event.srcElement。
5 - $('#box').addClass('wrap');
jQuery提供以上API来修改class名字
现代浏览器
document.querySelector('#box').classList.add('wrap'); 新的技巧使用新的classList API来添加,删除和变化class名字
var container = document.querySelector('#box');
container.classList.add('wrap');
container.classList.remove('wrap');
container.classList.toggle('wrap'); 传统遗留代码
var box = document.getElementById('box'),
hasClass = function (el, cl) {
var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
return !!el.className.match(regex);
},
addClass = function (el, cl) {
el.className += ' ' + cl;
},
removeClass = function (el, cl) {
var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
el.className = el.className.replace(regex, ' ');
},
toggleClass = function (el, cl) {
hasClass(el, cl) ? removeClass(el, cl) : addClass(el, cl);
};
addClass(box, 'drago');
removeClass(box, 'drago');
toggleClass(box, 'drago'); // if the element does not have a class of 'drago', add one. 6 - $('#list').next();
jQuery的next方法返回了当前元素后的元素
现代浏览器
var next = document.querySelector('#list').nextElementSibling; // IE9 nextElementSibling将会参考next元素节点,而不是任何节点(text,comment,element)。很不幸IE8及其以下。
传统遗留代码
var list = document.getElementById('list'),
next = list.nextSibling;
// we want the next element node...not text.
while ( next.nodeType > 1 ) next = next.nextSibling; 这里有几种方法来实现。这个例子中,我们检测跟随的指定nodeType。可以是文本, 元素或者一个注释。我们如果需要文本,我们则需要nodeType为1。如果next 。nodeType大于1,我们就忽略并且继,直到是一个文字节点。
7 - $('<div id=box></div>').appendTo('body');
除了查询,jQuery允许注入和创建元素。
传统遗留代码
var div = document.createElement('div');
div.id = 'box';
document.body.appendChild(div);这里没有什么现代方法来完成这个任务。这就是我们使用了很长时间的方法来实现。你需要添加内容到元素。你可以使用innerHTML或者createTextNode.
div.appendChild( document.createTextNode('wacka wacka') );
// or
div.innerHTML = 'wacka wacka'; 8 – $(document).ready(fn)
jQuery的document.ready方法非常的方便。允许我们在DOM加载后开始执行节点
现代浏览器
document.addEventListener('DOMContentLoaded', function() {
// have fun
}); 标准的HTML5,一但完成document加载DOMContentLoaded事件将会被触发
传统遗留代码
// http://dustindiaz.com/smallest-domready-ever
function ready(cb) {
/in/.test(document.readyState) // in = loadINg
? setTimeout('ready('+cb+')', 9)
: cb();
}
ready(function() {
// grab something from the DOM
});
以上代码,每隔9毫秒,将检测document.readyState状态。如果"loading"返回,document然而没有被完整解析(/in/。test(), 一旦解析完成,document.readyState将会等于“完成”,这个时候用户callback被执行
9 – $('.box').css('color', 'red');
如果可能的话,尽量使用class来提供样式。然而,有的时候,样式需要动态,所以需要作为一个属性插入。
现代浏览器
[].forEach.call( document.querySelectorAll('.box'), function(el) {
el.style.color = 'red'; // or add a class
});这里我们同样使用[].forEach.call()技巧来过滤所有的class为box的类,通过样式对象来使得他们变红。
传统遗留代码
var box = document.getElementsByClassName('box'), // refer to example #10 below for a cross-browser solution
i = box.length;
while ( i-- > 0 && (box[i].style.color = 'red') ); 这一次,我们使用while循环,如下:
var i = 0, len;
for ( len = box.length; i < len; i++ ) {
box[i].style.color = 'red';
}
10 – $()
很清楚,我们目的不是拷贝整个jQuery API。典型的,对于非jQuery对象,$或者$$用来作为DOM返回一个或者多个元素的快捷方式
现代浏览器
var $ = function(el) {
return document.querySelectorAll(el);
};
// Usage = $('.box'); 传统遗留代码
if ( !document.getElementsByClassName ) {
document.getElementsByClassName = function(cl, tag) {
var els, matches = [],
i = 0, len,
regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
// If no tag name is specified,
// we have to grab EVERY element from the DOM
els = document.getElementsByTagName(tag || "*");
if ( !els[0] ) return false;
for ( len = els.length; i < len; i++ ) {
if ( els[i].className.match(regex) ) {
matches.push( els[i]);
}
}
return matches; // an array of elements that have the desired classname
};
}
// Very simple implementation. We're only checking for an id, class, or tag name.
// Does not accept CSS selectors in pre-querySelector browsers.
var $ = function(el, tag) {
var firstChar = el.charAt(0);
if ( document.querySelectorAll ) return document.querySelectorAll(el);
switch ( firstChar ) {
case "#":
return document.getElementById( el.slice(1) );
case ".":
return document.getElementsByClassName( el.slice(1), tag );
default:
return document.getElementsByTagName(el);
}
};
// Usage
$('#container');
$('.box'); // any element with a class of box
$('.box', 'div'); // look for divs with a class of box
$('p'); // get all p elements 使用传统的方法不是很简单,这种情况你需要使用jQuery类似的类库。jQuery针对DOM优化,这就是为什么jQuery如此流行!以上代码并不支持复杂的CSS选择器。
总结
对于我们来说非常重要是我并没有鼓励你放弃jQuery。我几乎在每一个我的项目中都使用jQuery。希望大家喜欢!



