原生的強(qiáng)大DOM選擇器querySelector介紹
在傳統(tǒng)的 JavaScript 開發(fā)中,查找 DOM 往往是開發(fā)人員遇到的第一個(gè)頭疼的問題,原生的 JavaScript 所提供的 DOM 選擇方法并不多,僅僅局限于通過 tag, name, id 等方式來查找,這顯然是遠(yuǎn)遠(yuǎn)不夠的,如果想要進(jìn)行更為精確的選擇不得不使用看起來非常繁瑣的正則表達(dá)式,或者使用某個(gè)庫(kù)。事實(shí)上,現(xiàn)在所有的瀏覽器廠商都提供了 querySelector 和 querySelectorAll 這兩個(gè)方法的支持,甚至就連微軟也派出了 IE 8 作為支持這一特性的代表,querySelector 和 querySelectorAll 作為查找 DOM 的又一途徑,極大地方便了開發(fā)者,使用它們,你可以像使用 CSS 選擇器一樣快速地查找到你需要的節(jié)點(diǎn)。
querySelector 和 querySelectorAll 的使用非常的簡(jiǎn)單,就像標(biāo)題說到的一樣,它和 CSS 的寫法完全一樣,對(duì)于前端開發(fā)人員來說,這是難度幾乎為零的一次學(xué)習(xí)。假如我們有一個(gè) id 為 test 的 DIV,為了獲取到這個(gè)元素,你也許會(huì)像下面這樣:
document.getElementById("test");
現(xiàn)在我們來試試使用新方法來獲取這個(gè) DIV:
document.querySelector("#test"); document.querySelectorAll("#test")[0];
下面是個(gè)小演示:
感覺區(qū)別不大是吧,但如果是稍微復(fù)雜點(diǎn)的情況,原始的方法將變得非常麻煩,這時(shí)候 querySelector 和 querySelectorAll 的優(yōu)勢(shì)就發(fā)揮出來了。比如接下來這個(gè)例子,我們將在 document 中選取 class 為 test 的 div 的子元素 p 的第一個(gè)子元素,當(dāng)然這很拗口,但是用本文的新方法來選擇這個(gè)元素,比用言語來描述它還要簡(jiǎn)單。
document.querySelector("div.test>p:first-child"); document.querySelectorAll("div.test>p:first-child")[0];
下面是個(gè)小演示:
我是層里的 p 標(biāo)簽
現(xiàn)在應(yīng)該對(duì)于 querySelector、querySelectorAll 方法中的參數(shù)已經(jīng)非常明白了,是的,它接收的參數(shù)和 CSS 選擇器完全一致。querySelector 和 querySelectorAll 的區(qū)別在于 querySelector 用來獲取一個(gè)元素,而querySelectorAll 可以獲取多個(gè)元素。querySelector 將返回匹配到的第一個(gè)元素,如果沒有匹配的元素則返回 Null。querySelectorAll 返回一個(gè)包含匹配到的元素的數(shù)組,如果沒有匹配的元素則返回的數(shù)組為空。在本文最后一個(gè)例子中,我們使用 querySelectorAll 給所有 class 為 emphasis 的元素加粗顯示。
var emphasisText = document.querySelectorAll(".emphasis"); for( var i = 0 , j = emphasisText.length ; i < j ; i++ ){ emphasisText[i].style.fontWeight = "bold"; }
這是原生方法,比起jquery速度快,缺點(diǎn)是IE6、7不支持。
W3C的規(guī)范與庫(kù)中的實(shí)現(xiàn)
querySelector:return the first matching Element node within the node's subtrees. If there is no such node, the method must return null .(返回指定元素節(jié)點(diǎn)的子樹中匹配selector的集合中的第一個(gè),如果沒有匹配,返回null)
querySelectorAll:return a NodeList containing all of the matching Element nodes within the node's subtrees, in document order. If there are no such nodes, the method must return an empty NodeList. (返回指定元素節(jié)點(diǎn)的子樹中匹配selector的節(jié)點(diǎn)集合,采用的是深度優(yōu)先預(yù)查找;如果沒有匹配的,這個(gè)方法返回空集合)
這在BaseElement 為document的時(shí)候,沒有什么問題,各瀏覽器的實(shí)現(xiàn)基本一致;但是,當(dāng)BaseElement 為一個(gè)普通的dom Node的時(shí)候(支持這兩個(gè)方法的dom Node ),瀏覽器的實(shí)現(xiàn)就有點(diǎn)奇怪了,舉個(gè)例子:
<div class= "test" id= "testId" > <p><span>Test</span></p> </div> <script type= "text/javascript" > var testElement= document.getElementById( 'testId' ); var element = testElement.querySelector( '.test span' ); var elementList = document.querySelectorAll( '.test span' ); console.log(element); // <span>Test</span> console.log(elementList); // 1 </script>
按照W3C的來理解,這個(gè)例子應(yīng)該返回:element:null;elementList:[];因?yàn)樽鳛閎aseElement的 testElement里面根本沒有符合selectors的匹配子節(jié)點(diǎn);但瀏覽器卻好像無視了baseElement,只在乎selectors,也就是說此時(shí)baseElement近乎document;這和我們的預(yù)期結(jié)果不合,也許隨著瀏覽器的不斷升級(jí),這個(gè)問題會(huì)得到統(tǒng)一口徑!
人的智慧總是無窮的,Andrew Dupont發(fā)明了一種方法暫時(shí)修正了這個(gè)怪問題,就是在selectors前面指定baseElement的id,限制匹配的范圍;這個(gè)方法被廣泛的應(yīng)用在各大流行框架中;
Jquery的實(shí)現(xiàn):
var oldContext = context, old = context.getAttribute( "id" ), nid = old || id,
try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch (pseudoError) {} finally { if ( !old ) { oldContext.removeAttribute( "id" ); } }
先不看這點(diǎn)代碼中其他的地方,只看他如何實(shí)現(xiàn)這個(gè)方法的;這點(diǎn)代碼是JQuery1.6的片段;當(dāng)baseElement沒有ID的時(shí)候,給他設(shè)置一個(gè)id = "__sizzle__”,然后再使用的時(shí)候加在selectors的前面,做到范圍限制;context.querySelectorAll( "[id='" + nid + "'] " + query ;最后,因?yàn)檫@個(gè)ID本身不是baseElement應(yīng)該有的,所以,還需要移除:oldContext.removeAttribute( "id" ); ,Mootools的實(shí)現(xiàn):
var currentId = _context.getAttribute( 'id' ), slickid = 'slickid__' ; _context.setAttribute( 'id' , slickid); _expression = '#' + slickid + ' ' + _expression; context = _context.parentNode;
Mootools和Jquery類似:只不過slickid = 'slickid__';其實(shí)意義是一樣的;方法兼容性:FF3.5+/IE8+/Chrome 1+/opera 10+/Safari 3.2+;IE 8 :不支持baseElement為object;
相關(guān)文章
javaScript知識(shí)點(diǎn)總結(jié)(必看篇)
下面小編就為大家?guī)硪黄猨avaScript知識(shí)點(diǎn)總結(jié)(必看篇)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享 給大家,也給的大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06JavaScript中的正則表達(dá)式簡(jiǎn)明總結(jié)
這篇文章主要介紹了JavaScript中的正則表達(dá)式,簡(jiǎn)明總結(jié)了正則中的語法含義和RegExp對(duì)象,需要的朋友可以參考下2014-04-04解析DHTML,JavaScript,DOM,BOM以及WEB標(biāo)準(zhǔn)的描述
本篇文章是對(duì)DHTML,JavaScript,DOM,BOM以及WEB標(biāo)準(zhǔn)進(jìn)行了詳細(xì)的描述介紹,需要的朋友參考下2013-06-06深入理解JavaScript系列(37):設(shè)計(jì)模式之享元模式詳解
這篇文章主要介紹了深入理解JavaScript系列(37):設(shè)計(jì)模式之享元模式詳解,享元模式(Flyweight),運(yùn)行共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象,避免大量擁有相同內(nèi)容的小類的開銷(如耗費(fèi)內(nèi)存),使大家共享一個(gè)類(元類),需要的朋友可以參考下2015-03-03全選復(fù)選框JavaScript編寫小結(jié)(附代碼)
這篇文章主要介紹了全選”復(fù)選框JavaScript編寫,分別附上html和js代碼以供大家更深刻了解,具體操作步驟大家可查看下文的詳細(xì)講解,感興趣的小伙伴們可以參考一下。2017-08-08使用JavaScript制作一個(gè)簡(jiǎn)單的計(jì)數(shù)器的方法
這篇文章主要介紹了使用JavaScript制作一個(gè)簡(jiǎn)單的計(jì)數(shù)器的方法,用于計(jì)算網(wǎng)頁用戶的來訪次數(shù),需要的朋友可以參考下2015-07-07簡(jiǎn)單的ajax連接庫(kù)分享(不用jquery的ajax)
自己寫了一個(gè)簡(jiǎn)單的ajax連接庫(kù),沒有使用jquery的ajax,這個(gè)代碼要比jquery輕量,大家參考使用吧,2014-01-01詳解js運(yùn)算符單豎杠“|”與“||”的用法和作用介紹
在js開發(fā)應(yīng)用中我們通常會(huì)碰到“|”與“||”了,那么在運(yùn)算中“|”與“||”是什么意思呢?本篇文章主要介紹了詳解js運(yùn)算符單豎杠“|”與“||”的用法,有需要的可以了解一下。2016-11-11