你不需要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;
};

// https://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', 'https://www.webhek.com&example=something'); // returns 'something'

AJAX

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

阅读余下内容
 

《“你不需要jQuery(六)”》 有 1 条评论

  1. 等待DOM加载完成 这个我使用无效呀,最新版本的chrome浏览器

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注


京ICP备12002735号