你不需要jQuery(四)
jQuery是个好东西。它诞生于IE6在互联网称霸的那个时代。jQuery的存在让我们的代码能很好的兼容各种平台。
然而,到如今,浏览器技术已经取得了巨大的进步。我们可以自由的使用所有最新众多ES5/ES6提供的原生API,配合革命性的HTML5 API,我们对DOM的操作变得从未如此的容易。WEB开发人员突然发现,没有jQuery其实也能轻松高效的完成项目开发。
不要误会,jQuery仍然是一个强大的工具包,大多时候我们还是要优先选择它。然而,对于一些简单的任务,一些小项目,一个简单的页面,或者移动版网站上,我们使用简单的纯js也许更有效率。下面的10个技巧希望能给大家一些启发。
1. 监听页面加载完成事件
写jQuery代码时,我们通常首先做的是把代码包裹在$(document).ready()
里,这样,当DOM加载完成,可以操作时,包裹的代码才会去执行。除了使用jQuery,我们还可以使用 DOMContentLoaded
事件代替,下面是用例:
/ Add an event listener of DOMContentLoaded to the whole document and call an anonymous function. // You can then wrap your code in that function's brackets // and it will execute once loading is complete. document.addEventListener('DOMContentLoaded', function () { // Our hawaiian greeting is displayed as soon as the page loads, console.log('Aloha'); });
2. 查找/选择页面元素
曾经,我们如果想捕捉一个/一批元素,只能通过 id, class 和 tag 名称,jQuery给我提供了革命性的更具灵活性的基于css的查找方法。随着浏览器的进步,我们现在可以使用两个新型的原生JavaScript API – querySelector
和querySelectorAll:
// We can use document.querySelector to get the first element that matches a certain criteria. // It's only argument is a string containing one or more CSS selectors. var lochNess = document.querySelector(".monsters"); console.log("It's from Scotland - " + lochNess.textContent); // We can also get all elements of a certain type or class by using document.querySelectorAll. // This returns a NodeList of all the elements that fit our criteria. var scary = document.querySelectorAll(".monsters"); console.log("Hide and seek champions: "); for (var i = 0; i < scary.length; i++) { console.log(scary[i].innerHTML); }
<ul> <li class="monsters">Nessy</li> <li class="monsters">Big foot</li> <li class="monsters">La chupacabra</li> </ul>
3. 添加和移除事件监听器
事件监听是WEB应用里非常常见的操作。在过去,IE里的事件监听和其它浏览器的监听方法是不统一/不兼容的。但如今,我们只需要使用addEventListener
就可以了:
var btn = document.querySelectorAll("button"), list = document.querySelector("ul"); // We call the addEventListener method on our desired event target(in this case a button). // This will start a listener that will wait until a click is generated on the element. btn[0].addEventListener("click", function () { // When this button is clicked we want to enable zooming of our list. // To do this we add an event listener to our list itself, // so when the cursor hovers it, the enlarge function gets called. list.addEventListener("mouseover", enlarge); }); // To disable the zooming we can simply use removeEventListener. btn[1].addEventListener("click", function () { // Removing event listeners doesn't work on anonymous functions, so always use a named one. list.removeEventListener("mouseover", enlarge); }); // Let's create our enlarge function. var enlarge = function () { // Add class zoomed to the unordered list. list.classList.add("zoomed"); // When the cursor leaves the list return to normal size by removing the class. list.addEventListener("mouseout", function () { list.classList.remove("zoomed") }); }; // Now we want to be able to color the names by clicking them. // When a 'click' is registered on one of the list entries it should change its color to green. // Thanks to event delegation we can actually add an event listener to the whole parent object. // This way we don't have to add separate event listeners to each <li>. list.addEventListener("click", function (e) { // Make the coloring happen only to the clicked element by taking the target of the event. e.target.classList.add('green'); });
<button>Enable zoom</button> <button>Disable zoom</button> <br><br> Click on any of the names to color them green <ul> <li>Chewbacca</li> <li>Han Solo</li> <li>Luke</li> <li>Boba fett</li> </ul>
.green { color: green; } .zoomed { cursor: pointer; font-size: 23px; }
addEventListener
的用法看起来跟jQuery里的事件监听用法非常相似。
4. 对类和属性的操作
以前,执行对于页面元素css类的各种操作(查找、增加、删除等),如果不用jQuery,那是一件非常麻烦的事情。这样的历史已经一去不复返了,这样要感谢classList 属性。而使用 setAttribute, 我们可对元素属性进行操作。
var btn = document.querySelectorAll("button"), div = document.querySelector("#myDiv"); btn[0].addEventListener("click", function () { // Get any attribute easily. console.log(div.id); }); // Element.classList stores all classes of the element in the form of a DOMTokenList. var classes = div.classList; btn[1].addEventListener("click", function () { console.log(classes); }); btn[2].addEventListener("click", function () { // 可以增加和移除某个类名 classes.add("red"); }); btn[3].addEventListener("click", function () { // 可以翻转某个类名 classes.toggle("hidden"); });
<div id='myDiv' class="square"></div> <button>Display id</button> <button>Display classes</button> <button>Color red</button> <button>Toggle visibility</button>
.square { width: 100px; height: 100px; margin-bottom: 20px; border: 1px solid grey; border-radius: 5px; } .hidden { visibility: hidden; } .red { background-color: red; }
5. 获取或设置元素的内容
jQuery里有个非常方便的 text() 和 html() 方法,相对应的,在元素JavaScript里,我们可以使用 textContent 和 innerHTML 两个属性,这两个属性其实并不是新出现的:
var myText = document.querySelector("#myParagraph"), btn = document.querySelectorAll("button"); // We can easily get the text content of a node and all its descendants. var myContent = myText.textContent; console.log("textContent: " + myContent); // When using textContent to alter the text of an element // it deletes the old content and replaces it with new. btn[0].addEventListener('click', function () { myText.textContent = " Koalas are the best animals "; }); // If we want to grab all the HTML in a node (including the tags) we can use innerHTML. var myHtml = myText.innerHTML; console.log("innerHTML: " + myHtml); // To change the html simply supply new content. // Of course we aren't limited to text only this time. btn[1].addEventListener('click', function () { myText.innerHTML = "<button> Penguins are the best animals </button>"; });
<p id="myParagraph"><strong> Which are the best animals? </strong></p> <button>Koalas</button> <br> <button>Penguins</button>
6. 循环数组
jQuery里提供了很多实验的方法,比如each()
和 map()
,而在新版的JavaScript api里,我们有了原生的 forEach 和 map ,需要注意的是,它们参数的用法有些不同,并且在回调函数里 this 的代表性也有些不同。
var ninjaTurtles = ["Donatello", "Leonardo", "Michelangelo", "Raphael"]; // ForEach automatically iterates through an array. ninjaTurtles.forEach(function (entry) { console.log(entry); }); // The map method calls a function on every element of an array and creates a new array with the results. var lovesPizza = ninjaTurtles.map(function (entry) { return entry.concat(" loves pizza!"); }); console.log(lovesPizza);
7. AJAX
新版的JavaScript API里提供了一个全新的可以实现ajax的API——fetch,这个api采用了全新的 Promise 架构,使用起来更方便,更灵活,详细用法请参考《你不需要jQuery(三):新AJAX方法fetch() 》。
总结
如果你追求极简,不允许页面有半点臃肿,以更快的加载速度和更好的用户体验为目标,那么,你应该试试上面的技巧,不要因为一个很小的功能而滥用jQuery,浏览器在革新,JavaScript在进步,原生的API逐渐取代jQuery是潮流,WEB程序员应多关注这方面的知识技巧,不是吗?