你不需要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() 》。
等待DOM加载完成 这个我使用无效呀,最新版本的chrome浏览器