原生的強大DOM選取器querySelector介紹,domqueryselector

來源:互聯網
上載者:User

原生的強大DOM選取器querySelector介紹,domqueryselector

在傳統的 JavaScript 開發中,尋找 DOM 往往是開發人員遇到的第一個頭疼的問題,原生的 JavaScript 所提供的 DOM 選擇方法並不多,僅僅局限於通過 tag, name, id 等方式來尋找,這顯然是遠遠不夠的,如果想要進行更為精確的選擇不得不使用看起來非常繁瑣的Regex,或者使用某個庫。事實上,現在所有的瀏覽器廠商都提供了 querySelector 和 querySelectorAll 這兩個方法的支援,甚至就連微軟也派出了 IE 8 作為支援這一特性的代表,querySelector 和 querySelectorAll 作為尋找 DOM 的又一途徑,極大地方便了開發人員,使用它們,你可以像使用 CSS 選取器一樣快速地尋找到你需要的節點。

querySelector 和 querySelectorAll 的使用非常的簡單,就像標題說到的一樣,它和 CSS 的寫法完全一樣,對於前端開發人員來說,這是難度幾乎為零的一次學習。假如我們有一個 id 為 test 的 DIV,為了擷取到這個元素,你也許會像下面這樣:

document.getElementById("test");
現在我們來試試使用新方法來擷取這個 DIV:

document.querySelector("#test");document.querySelectorAll("#test")[0];

下面是個小示範:

我是 id 為 test 的 div

感覺區別不大是吧,但如果是稍微複雜點的情況,原始的方法將變得非常麻煩,這時候 querySelector 和 querySelectorAll 的優勢就發揮出來了。比如接下來這個例子,我們將在 document 中選取 class 為 test 的 div 的子項目 p 的第一個子項目,當然這很拗口,但是用本文的新方法來選擇這個元素,比用言語來描述它還要簡單。

document.querySelector("div.test>p:first-child");document.querySelectorAll("div.test>p:first-child")[0];

下面是個小示範:

我是層裡的 p 標籤

現在應該對於 querySelector、querySelectorAll 方法中的參數已經非常明白了,是的,它接收的參數和 CSS 選取器完全一致。querySelector 和 querySelectorAll 的區別在於 querySelector 用來擷取一個元素,而querySelectorAll 可以擷取多個元素。querySelector 將返回匹配到的第一個元素,如果沒有匹配的元素則返回 Null。querySelectorAll 返回一個包含匹配到的元素的數組,如果沒有匹配的元素則返回的數組為空白。在本文最後一個例子中,我們使用 querySelectorAll 給所有 class 為 emphasis 的元素加粗顯示。

var emphasisText = document.querySelectorAll(".emphasis");for( var i = 0 , j = emphasisText.length ; i < j ; i++ ){  emphasisText[i].style.fontWeight = "bold";}

這是原生方法,比起jquery速度快,缺點是IE6、7不支援。

W3C的規範與庫中的實現

querySelector:return the first matching Element node within the node's subtrees. If there is no such node, the method must return null .(返回指定元素節點的子樹中匹配selector的集合中的第一個,如果沒有匹配,返回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. (返回指定元素節點的子樹中匹配selector的節點集合,採用的是深度優先預尋找;如果沒有匹配的,這個方法返回空集合)

這在BaseElement 為document的時候,沒有什麼問題,各瀏覽器的實現基本一致;但是,當BaseElement 為一個普通的dom Node的時候(支援這兩個方法的dom Node ),瀏覽器的實現就有點奇怪了,舉個例子:

<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的來理解,這個例子應該返回:element:null;elementList:[];因為作為baseElement的 testElement裡面根本沒有符合selectors的匹配子節點;但瀏覽器卻好像無視了baseElement,只在乎selectors,也就是說此時baseElement近乎document;這和我們的預期結果不合,也許隨著瀏覽器的不斷升級,這個問題會得到統一口徑!

人的智慧總是無窮的,Andrew Dupont發明了一種方法暫時修正了這個怪問題,就是在selectors前面指定baseElement的id,限制匹配的範圍;這個方法被廣泛的應用在各大流行架構中;

Jquery的實現:

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"  );}}

先不看這點代碼中其他的地方,只看他如何?這個方法的;這點代碼是JQuery1.6的片段;當baseElement沒有ID的時候,給他設定一個id = "__sizzle__”,然後再使用的時候加在selectors的前面,做到範圍限制;context.querySelectorAll( "[id='" + nid + "'] " + query ;最後,因為這個ID本身不是baseElement應該有的,所以,還需要移除:oldContext.removeAttribute( "id" ); ,Mootools的實現:

var  currentId = _context.getAttribute( 'id' ), slickid = 'slickid__' ;_context.setAttribute( 'id' , slickid);_expression = '#'  + slickid + ' '  + _expression;context = _context.parentNode;

Mootools和Jquery類似:只不過slickid = 'slickid__';其實意義是一樣的;方法相容性:FF3.5+/IE8+/Chrome 1+/opera 10+/Safari 3.2+;IE 8 :不支援baseElement為object;

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.