炫意html5
最早CSS3和HTML5移动技术网站之一

你不需要jQuery(六)


为什么要用原生JavaScript?

jQuery的一个好处是能跨浏览器兼容,比如ie、火狐浏览器、谷歌浏览器、Safari等。但这样大而广的兼容带来的弊病是代码的臃肿,性能的折中,体积的增加。这不仅仅是增加了网页加载时间,同时浏览器对JavaScript解析速度也大幅度的下降。

原生 JavaScript APIs

下面是一个清单,描述了一些跟jQuery API等效的原生 JavaScript API。最新的谷歌浏览器、火狐浏览器等对这些原生API都支持的非常好,而IE浏览器需要IE9以上。

顺便说说一句: 很多的现代新版的 ECMAScript 5、6 API 都严重的受 jQuery 影响,因此它们的接口都非常的相似,这样我们学起来也比较容易。感谢 jQuery!

查找、搜索、选择

HTML5 提供了两个新的 API 用来在DOM里进行查找、选择。document.querySelector() 返回匹配的第一个元素, document.querySelectorAll() 返回一个 node list, 里面存储了所有匹配的元素。

var firstClass = document.querySelector('.some-class');
var firstId = document.querySelector('#some-id');
var firstData = document.querySelector('[data-example]');
var allClasses = document.querySelectorAll('.some-class');
var allData = document.querySelectorAll('[data-example]');

变量数组/集合

// Arrays and node lists
var elems = document.querySelectorAll('.some-class');
for (var i = 0; i < elems.length; i++) {
console.log(i) // index
console.log(elems[i]) // object
}
// Objects
var obj = {
apple: 'yum',
pie: 3.214,
applePie: true
};
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
console.log(prop); // key
console.log(obj[prop]); // value
}
}

Class 操作

对CSS类的增加、删除、查找,以及探测。

var elem = document.querySelector('#some-element');
elem.classList.add('some-class'); // Add class
elem.classList.remove('some-other-class'); // Remove class
elem.classList.toggle('some-other-class'); // Add or remove class
if ( elem.classList.contains('some-third-class') ) { // Check for class
console.log('yep!');
}

样式操作

var elem = document.querySelector('#some-element');
elem.style.color; // Get a CSS attribute
elem.style.color = 'rebeccapurple'; // Set a CSS attribute
elem.style.minHeight; // Get a CSS attribute
elem.style.minHeight = '200px'; // Set a CSS attribute

属性操作

对属性的修改、增加、删除,以及存在测试

var elem = document.querySelector('#some-element');
elem.getAttribute('data-example'); // Get data attribute
elem.setAttribute('data-example', 'Hello world'); // Set data attribute
if ( elem.hasAttribute('data-example') ) { // Check data attribute
console.log('yep!');
}

通过这两个方法,我们可以对所有的各种元素属性进行操作。但实际上,我们还有一种更简单的操作方式:

var elem = document.querySelector('#some-element');
// Set an ID
elem.setAttribute('id', 'new-id');
elem.id = 'new-id';
// Set width
elem.setAttribute('width', '200px');
elem.width = '200px';
// Get title
elem.getAttribute('title');
elem.title;

时间监听器

监听点击、鼠标悬停等事件。

var elem = document.querySelector('.some-class');
elem.addEventListener('click', function(event) {
// Do stuff
}, false);

如果你想让多个事件执行同一种操作,你可以将操作封装在一个函数里:

var elem = document.querySelector('.some-class');
var someFunction = function (event) {
// Do stuff
}
elem.addEventListener('click', someFunction, false);
elem.addEventListener('mouseover', someFunction, false);

如果你需要在回调函数里传递多个参数,可以使用 .bind() API。绑定时,第一个参数会被 this 取代,而 event 对象会自动的扩展到最后一个参数。

var elem = document.querySelector('.some-class');
var someFunction = function (var1, var2, var3, event) {
// Do stuff
}
elem.addEventListener('click', someFunction.bind(null, var1, var2, var3), false);
elem.addEventListener('mouseover', someFunction.bind(null, var1, var2, var3), false);

注意: .bind() 是一个比较新的函数,有些老版的浏览器未必支持这个方法,所以,最后使用最新版的浏览器。

对于有名称的函数,我们可以执行删除监听器的操作。

elem.removeEventListener('click', someFunction, false);
elem.removeEventListener('mouseover', someFunction, false);

对在多个元素上监听同一种事件的操作,我们可以遍历每个元素,分别给它们添加监听器。但一个种更好的方法是,监听整个页面文档,然后过滤出你需要的元素。

// Function to filter what's clicked and run your functions
var eventHandler = function () {
// Get the clicked element
var toggle = event.target;
// If clicked element is the one you're looking for, run your methods
if ( toggle.hasAttribute('data-example') || toggle.classList.contains('sample-class') ) {
event.preventDefault(); // Prevent default click event
someMethod( the, arguments, to, pass, in );
}
};
// Listen for all click events on the document
document.addEventListener('click', eventHandler, false);

等待DOM加载完成

我们写WEB应用时很多js代码都需要在DOM加载完成后才能执行。现代浏览器都提供了 DOMContentReady 事件监听器,只有在DOM加载完成时,这个事件才会触发。 下面用原生JavaScript写的 ready() 方法和jQuery里的同名方法功能是一样的。

var ready = function ( fn ) {
// Sanity check
if ( typeof fn !== 'function' ) return;
// If document is already loaded, run method
if ( document.readyState === 'complete'  ) {
return fn();
}
// Otherwise, wait until document is loaded
document.addEventListener( 'DOMContentLoaded', fn, false );
};
// Example
ready(function() {
// Do stuff...
});

HTML内容

var elem = document.querySelector('#some-element');
var html = elem.innerHTML; // Get HTML
elem.innerHTML = 'Hello world!'; // Set HTML

判断元素是否在可见视窗内(viewport)?

var isInViewport = function ( elem ) {
var distance = elem.getBoundingClientRect();
return (
distance.top >= 0 &&
distance.left >= 0 &&
distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
distance.right <= (window.innerWidth || document.documentElement.clientWidth)
);
};
var elem = document.querySelector('#some-element');
isInViewport(elem); // Boolean: returns true/false

子元素操作

获取元素的全部子元素。

var elem = document.querySelector('#some-element');
var all = elem.childNodes;

获取元素的第一个子元素。

var elem = document.querySelector('#some-element');
var first = elem.firstChild;

通过ID,类名、属性获取第一个子元素。

var elem = document.querySelector('#some-element');
var firstMatch = elem.querySelector('.sample-class');

通过ID,类名、属性获取匹配的子元素。

var elem = document.querySelector('#some-element');
var allMatches = elem.querySelectorAll('.sample-class');

临近元素

var getSiblings = function (elem) {
var siblings = [];
var sibling = elem.parentNode.firstChild;
for ( ; sibling; sibling = sibling.nextSibling ) {
if ( sibling.nodeType === 1 && sibling !== elem ) {
siblings.push( sibling );
}
}
return siblings;
};
var elem = document.querySelector('#some-element');
var siblings = getSiblings(elem);

获取链接参数

从URL上获取 querystring 查询参数。

var getQueryString = function ( field, url ) {
var href = url ? url : window.location.href;
var reg = new RegExp( '[?&]' + field + '=([^&#]*)', 'i' );
var string = reg.exec(href);
return string ? string[1] : null;
};
// http://www.webhek.com&this=chicken&that=sandwich
var thisOne = getQueryString('this'); // returns 'chicken'
var thatOne = getQueryString('that'); // returns 'sandwich'
var anotherOne = getQueryString('another'); // returns null
var yetAnotherOne = getQueryString('example', 'http://www.webhek.com&example=something'); // returns 'something'

AJAX

新版的JavaScript API里提供了一个全新的可以实现ajax的API——fetch,这个api采用了全新的 Promise 架构,使用起来更方便,更灵活,详细用法请参考《你不需要jQuery(三):新AJAX方法fetch() 》。

炫意HTML5 » 你不需要jQuery(六)

CSS3教程HTML5教程