摘要:瀏覽器原生提供的幾個(gè)找到元素的方法為網(wǎng)頁全局唯一。匹配包含的元素匹配包含和的元素級(jí)聯(lián)用法和相似返回一個(gè)。以上返回?cái)?shù)組的方法,返回的都是的。
那是個(gè)夜黑風(fēng)高的夜晚,我遇到了一個(gè)按鈕:
嗯,我要選中它,我敲下了一行代碼:
const submitButton = document.querySelector("button[type="submit"]");
這對(duì)于精通 document.querySelector 的函數(shù)名書寫方式的我來說,簡直就像吃下四兩飯一樣簡單!
但是。
我們知道,document.querySelector 接收一個(gè)選擇器字符串,返回第一個(gè)匹配的 DOM 元素,所以如果頁面上只有一個(gè) button[type="submit"] 或者這個(gè) button[type="submit"] 在 html 中是第一個(gè)時(shí),我這個(gè)方法是無懈可擊的。
然后,我發(fā)現(xiàn)頁面上竟然存在兩個(gè) button[type="submit"] 類型的按鈕(黑人問號(hào)???)。
我對(duì)比了一下差異:
先不八卦為什么頁面上有兩個(gè)差不多的按鈕,但能初步判定的是,他們長得很像,嗯。
那么,問題來了,我怎么選中那個(gè)搜索框,我把問題拋給了自以為是的自己,得到了幾個(gè)回答。
分身 A:改用 selectorSelectorAll 拿到第二個(gè)不就行了嘛!
const allSubmitButton = document.querySelectorAll("button[type="submit"]"); const submitButton = allSubmitButton[1];
這方法貌似不錯(cuò),但萬一這兩個(gè)按鈕對(duì)調(diào)位置了怎么辦?
分身 B: 那選擇器寫全一點(diǎn),也匹配『搜索』這兩個(gè)字不就可以把『提交』那個(gè)按鈕給拍除掉了嘛!
const submitButton = document.querySelector("button[type="submit"][innerText="搜索"]");
打印出來一看,嗯,怎么輸出是 null???
分身 B: 那個(gè),那個(gè)。。。innerText 是我編出來的,我不知道正確的要怎么寫。
嗯,雖然 B 寫錯(cuò)了語法(哪個(gè)程序員會(huì)不寫錯(cuò)語法?),但限定了兩個(gè)條件,type="submit" 和 innerText="搜索", 能唯一匹配搜索按鈕了,這個(gè)思路是對(duì)的。
那么,正確的語法是什么呢?
苦苦搜索半天,無果。
分身 C: 那就是寫不出這樣的選擇器吧,還是用 JS 來做吧 :)
分身 A: 這么簡單的需求,CSS 是萬能的,為什么要用 Javascript?
分身 B: 對(duì),Hail CSS!
。。。那我們就借此機(jī)會(huì)溫習(xí)一下找到一個(gè) DOM 元素有哪些方法吧。
瀏覽器原生提供的幾個(gè)找到 DOM 元素的方法 document.getElementByIdId 為網(wǎng)頁全局唯一。
document.getElementById("id");
注意,與其他方法不一樣,getElementById 只能被全局對(duì)象 document 調(diào)用,否則會(huì)報(bào)錯(cuò):
document.getElementById("parentId").getElementById("childId"); // Uncaught TypeError: document.getElementById(...).getElementById is not a function
因?yàn)?Id 是全局唯一的,所以上面第二種寫法自然也顯得沒有必要。
Id 對(duì)大小寫敏感(除非文檔被聲明為特殊類型如: XHTML, XUL),所以以下兩種寫法并不等同:
document.getElementById("id"); documen.getElementById("ID");element.getElementsByClassName
這里的 element 指代網(wǎng)頁中有效的 DOM 元素,包含 document。
返回一個(gè) HTMLCollection。
// 匹配 class 包含 "submit" 的元素 document.getElementsByClassName("submit"); // 匹配 class 包含 "submit" 和 "button" 的元素 document.getElementsByClassName("submit button"); // 級(jí)聯(lián) cons selectedElement = document.getElementById("app-container"); selectedElement.getElementsByClassName("submit button");element.getElementsByName
用法和 getElementsByClassName 相似, 返回一個(gè) HTMLCollection。
element.getElementsByTagName用法和 getElementsByClassName 相似, 返回一個(gè) HTMLCollection。
element.querySelector再熟悉不過的接口了,傳入 CSS 選擇器,返回第一個(gè)找到的元素。
element.querySelectorAll以上返回?cái)?shù)組的方法,getElementsByName、getElementsByTagName、getElementsByTagNameNS、querySelectorAll 返回的都是 Array-like 的 HTMLCollection。
要像對(duì)數(shù)組一樣對(duì) HTMLCollection 進(jìn)行操作(使用數(shù)組的 forEach、filter 等方法),則需要將他們轉(zhuǎn)化為數(shù)組:
const buttonCollection = document.getElementsByClassName("submit"); // const buttonArray = Array.prototype.slice.call(buttonCollection); const buttonArray = [].slice.call(buttonCollection); buttonArray.forEach(item => { // do something });querySelector 與 getElementsByName、getElementsByClassName 和 getElementsByTagName 的細(xì)微差異
注意,對(duì)于都是返回 HTMLCollection 的方法,與 querySelector 不同的是,getElementsByName、getElementsByClassName、getElementsByTagName 返回的 HTMLCollection 是一個(gè)引用類型的 HTMLCollection 。
也就是:
querySelectorAll 獲取的是當(dāng)時(shí)文檔中匹配選擇器的 DOM 元素,不包含后面插入到文檔中的元素,如果文檔有更新,則需要重新獲取
而 getElementsByName、getElementsByClassName 和 getElementsByTagName 則能隨時(shí)反映文檔中匹配對(duì)應(yīng)規(guī)則的元素,包含后面插入到文檔中的元素,如果文檔有更新,不需要重新獲取
這個(gè)說法有點(diǎn)類似拷貝和引用的關(guān)系。
話不多說,我們直接寫點(diǎn)代碼做個(gè)測試:
const createElement = (func) => { const key = "myCustomElement"; let element; switch (func) { case "getElementsByName": element = document.createElement("div"); element.setAttribute("name", key); break; case "getElementsByClassName": element = document.createElement("div"); element.setAttribute("class", key); break; case "getElementsByTagName": element = document.createElement(key); break; case "querySelectorAll": element = document.createElement("div"); element.className = key; break; default: element = document.createElement("div"); } return element; } const getCollection = (root, func) => { const key = "myCustomElement"; let element; if (func === "getElementsByName") { return document.getElementsByName(key); } if (func === "querySelectorAll") { return root.querySelectorAll(`.${key}`); } return root[func](key); } const testFunc = (func) => { const result = []; // 避免 getElementsByClassName 和 querySelectorAll 在統(tǒng)一環(huán)境的影響,創(chuàng)建一個(gè)獨(dú)立的容器測試 const container = document.createElement("div"); document.body.append(container); // 1. 插入一個(gè) container.append(createElement(func)); // 2. 看下現(xiàn)在有多少個(gè) const collection = getCollection(container, func); result.push(collection.length); // 3. 繼續(xù)插入一個(gè) container.append(createElement(func)); // 4. 看下現(xiàn)在有多少個(gè) result.push(collection.length); return result; }; console.log("getElementsByName", testFunc("getElementsByName")); // [1, 2] console.log("getElementsByClassName", testFunc("getElementsByClassName")); // [1, 2] console.log("getElementsByTagName", testFunc("getElementsByTagName")); // [1, 2] console.log("querySelectorAll", testFunc("querySelectorAll")); // [1, 1] // 注意這個(gè)輸出 // 輸出的是: /* getElementsByName [1, 2] getElementsByClassName [1, 2] getElementsByTagName [1, 2] querySelectorAll [1, 1] */還有什么方法可以根據(jù) innerText 找到指定元素
回到本文討論的問題,貌似瀏覽器原生并沒有提供類似 document.getElementByInnerText ?
找了一圈貌似沒有,那只能借用 Javascript 了。
回憶一下需要找到的元素是:
使用原生 Javascript可以使用 querySelectorAll :
let foundElement = null; const elementsCollection = document.querySelectorAll("button[type="submit"]"); const elementArray = [].slice.call(elementsCollection); /* // 使用 Array.forEach 遍歷,缺點(diǎn)是找到后沒法 break elementArray.forEach(element => { if (element.innerText.trim() === "搜索") { foundElement = element; } // 或者使用正則 /* if (/^s{0,}搜索s{0,}$/.test(element.innerText)) { foundElement = element; } */ }); */ /* // 或使用 for-loop 找到后提前 break const len = inputElementArray.length; for (let i = 0; i < len; i++) { if (elementArray[i].innerText.trim()) { foundElement = elementArray[i]; break; } } */ // 或使用 filter const foundElementArray = elementArray.filter(element => element.innerText.trim() === "搜索"); if (foundElementArray.length) { foundElement = foundElementArray[0]; }題外話:innerText 與 innerHTML、textContent 的差異?
簡而言之:
innerText 獲取元素第一層的文本內(nèi)容,不包含標(biāo)簽;
innerHTML 如其名獲取內(nèi)部 HTML 片段,包含標(biāo)簽;
textContent 類似 innerText,不過會(huì)在去掉標(biāo)簽后將嵌套的純文本內(nèi)容也獲取出來。
MDN textContent"s difference from innerText and innerHTML
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89049.html
摘要:希望在做所有事情之前,操作文檔。不受層級(jí)限制子選擇器在給定的父元素下匹配所有子元素。相鄰選擇器匹配所有緊接在元素后的元素。判斷當(dāng)前對(duì)象中的某個(gè)元素是否包含指定類名,包含返回,不包含返回下標(biāo)過濾器精確選出指定下標(biāo)元素獲取第個(gè)元素。 原文鏈接 http://blog.poetries.top/2016... 首先,來了解一下jQuery學(xué)習(xí)的整體思路 showImg(https://seg...
摘要:前端開發(fā)在年依然持續(xù)火熱,本文將對(duì)熱點(diǎn)事件做一個(gè)總結(jié)。版的和協(xié)議在前端領(lǐng)域,一直獨(dú)占鰲頭。年又發(fā)布了一個(gè)重大的版本更新。主要是配合使用了服務(wù)工作線程。而且還提供了供前端開發(fā)者接入??焖侔l(fā)布了和在悄悄地跳過之后,在月號(hào)正式發(fā)布。 譯者按: 老技術(shù)日趨成熟,新技術(shù)層出不窮。 原文: A recap of front-end development in 2017 譯者: Fundebu...
摘要:大家應(yīng)該非常熟悉的方法那么如何在不引用的情況下同樣實(shí)現(xiàn)這個(gè)功能呢本文就介紹使用原生來獲取樣式的方法作者原文鏈接我們來翻翻元素樣式的族譜是什么方法可以獲取當(dāng)前元素所有最終使用的屬性值返回的是一個(gè)樣式聲明對(duì)象只讀也就是說獲取到的不僅僅是我們自 大家應(yīng)該非常熟悉jQuery的css()方法,那么如何在不引用jQuery的情況下同樣實(shí)現(xiàn)這個(gè)功能呢?本文就介紹使用原生JS來獲取樣式的方法. 作者...
摘要:大家應(yīng)該非常熟悉的方法那么如何在不引用的情況下同樣實(shí)現(xiàn)這個(gè)功能呢本文就介紹使用原生來獲取樣式的方法作者原文鏈接我們來翻翻元素樣式的族譜是什么方法可以獲取當(dāng)前元素所有最終使用的屬性值返回的是一個(gè)樣式聲明對(duì)象只讀也就是說獲取到的不僅僅是我們自 大家應(yīng)該非常熟悉jQuery的css()方法,那么如何在不引用jQuery的情況下同樣實(shí)現(xiàn)這個(gè)功能呢?本文就介紹使用原生JS來獲取樣式的方法. 作者...
摘要:大家應(yīng)該非常熟悉的方法那么如何在不引用的情況下同樣實(shí)現(xiàn)這個(gè)功能呢本文就介紹使用原生來獲取樣式的方法作者原文鏈接我們來翻翻元素樣式的族譜是什么方法可以獲取當(dāng)前元素所有最終使用的屬性值返回的是一個(gè)樣式聲明對(duì)象只讀也就是說獲取到的不僅僅是我們自 大家應(yīng)該非常熟悉jQuery的css()方法,那么如何在不引用jQuery的情況下同樣實(shí)現(xiàn)這個(gè)功能呢?本文就介紹使用原生JS來獲取樣式的方法. 作者...
閱讀 1263·2021-11-08 13:25
閱讀 1452·2021-10-13 09:40
閱讀 2783·2021-09-28 09:35
閱讀 748·2021-09-23 11:54
閱讀 1139·2021-09-02 15:11
閱讀 2446·2019-08-30 13:18
閱讀 1681·2019-08-30 12:51
閱讀 2697·2019-08-29 18:39