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