搜尋

首頁  >  問答  >  主體

在JavaScript中,querySelector和querySelectorAll與getElementsByClassName和getElementById的區別

<p>我想知道<code>querySelector</code>和<code>querySelectorAll</code>與<code>getElementsByClassName</code>和<什麼區別? </p> <p>從這個連結中,我了解到使用<code>querySelector</code>,我可以寫<code>document.querySelector(".myclass")</code>來取得具有類別名稱< ;code>myclass</code>的元素,以及<code>document.querySelector("#myid")</code>來取得具有ID<code>myid</code>的元素。但是我已經可以使用<code>getElementsByClassName</code>和<code>getElementById</code>來實現這個功能。哪個應該優先選擇? </p> <p>另外,我在XPages工作,ID是動態產生的,包含冒號,看起來像這樣<code>view:_id1:inputText1</code>。所以當我寫<code>document.querySelector("#view:_id1:inputText1")</code>時,它不起作用。但是當我寫<code>document.getElementById("view:_id1:inputText1")</code>時,它起作用。有任何想法為什麼會這樣? </p>
P粉442576165P粉442576165492 天前688

全部回覆(2)我來回復

  • P粉008829791

    P粉0088297912023-08-22 20:21:16

    對於這個答案,我將querySelectorquerySelectorAll稱為querySelector*,將getElementByIdgetElementsByClassNamegetElementsByTagName getElementsByName稱為getElement*。

    這些資訊的許多資訊可以在規範中進行驗證,很多是我在寫時執行的各種基準測試得出的。規格:https://dom.spec.whatwg.org/

    #主要區別

    1. querySelector*更靈活,因為您可以傳遞任何CSS3選擇器,而不僅僅是簡單的id、tag或class。
    2. querySelector*的效能會隨其所呼叫的DOM的大小而變化。準確地說,querySelector*呼叫以O(n)時間運行,而getElement*呼叫以O(1)時間運行,其中n是呼叫所在元素或文件的所有子元素的總數。
    3. 這些呼叫的回傳類型有所不同。 querySelectorgetElementById都傳回單一元素。 querySelectorAllgetElementsByName都回傳NodeList。 getElementsByClassNamegetElementsByTagName都回傳HTMLCollection。 NodeList和HTMLCollection都被稱為元素的集合。
    4. 集合可以分別傳回「live」或「static」集合。這在它們返回的實際類型中沒有反映出來。 getElements*呼叫傳回live集合,而querySelectorAll傳回static集合。據我理解,live集合包含DOM中元素的引用,而static集合包含元素的副本。您也可以查看下面的@Jan Feldmann的評論,以獲取不同的角度。我還沒有找到一個好的方法將其納入我的答案,但它可能是一個更準確的理解。

    這些概念在下表中總結。

    Function               | Live? | Type           | Time Complexity
    querySelector          |       | Element        |  O(n)
    querySelectorAll       |   N   | NodeList       |  O(n)
    getElementById         |       | Element        |  O(1)
    getElementsByClassName |   Y   | HTMLCollection |  O(1)
    getElementsByTagName   |   Y   | HTMLCollection |  O(1)
    getElementsByName      |   Y   | NodeList       |  O(1)
    

    詳細資訊、提示和範例

    • HTMLCollection不像NodeList那樣類似數組,不支援.forEach()。我發現擴展運算符對繞過這個問題很有用:

      [...document.getElementsByClassName("someClass")].forEach()

    • 每個元素和全域document都可以存取所有這些函數,除了getElementByIdgetElementsByName,它們只在document上實作。

    • 鍊式使用getElement*呼叫而不是使用querySelector*將提高效能,特別是在非常大的DOM上。即使在小的DOM和/或非常長的鏈上,通常也更快。然而,除非您知道需要效能,否則應該優先選擇querySelector*的可讀性。 querySelectorAll通常更難重寫,因為您必須在每個步驟中從NodeList或HTMLCollection中選擇元素。例如,以下程式碼不起作用

      document.getElementsByClassName("someClass").getElementsByTagName("div")

      #因為您只能在單一元素上使用getElements*,而不是集合,但如果您只想要一個元素,那麼:

      document.querySelector("#someId .someClass div")

      #可以寫成:

      document.getElementById("someId").getElementsByClassName("someClass")[0].getElementsByTagName("div")[0]

      #注意在傳回集合的每個步驟中使用[0],以取得集合的第一個元素,最終結果只有一個元素,就像使用querySelector一樣。

    • 由於所有元素都可以使用querySelector*和getElement*調用,因此可以同時使用這兩個調用進行鍊式操作,這在您想要一些性能提升但無法避免使用無法用getElement*調用編寫的querySelector時非常有用。

    • 儘管通常很容易判斷一個選擇器是否可以只使用getElement*呼叫來編寫,但有一種情況可能不明顯:

      document.querySelectorAll(".class1.class2")

      #可以重寫為

      document.getElementsByClassName("class1 class2")

    • #在使用querySelector*獲取的靜態元素上使用getElement*將導致元素相對於querySelector複製的靜態DOM子集是動態的,但相對於完整文檔DOM是靜態的...這就是簡單的動態/靜態元素解釋開始分崩離析的地方。您應該盡量避免需要擔心這個問題的情況,但如果確實存在這種情況,請記住querySelector*呼叫在傳回引用之前會複製它們找到的元素,而getElement*呼叫則會直接取得引用而不複製。

    • querySelector*和getElementById前序、深度優先的方式遍歷元素,在規範中稱為「樹順序」。對於其他getElement*調用,從規範中我無法確定它們是否與樹順序相同,但getElementsByClassName(".someClass")[0]可能在每個瀏覽器中結果不可靠。 getElementById("#someId")應該是可靠的,即使您的頁面上有多個相同的id副本。

    • 當我在處理無限滾動頁面時,我不得不研究這個問題,我認為這可能是一個常見的情況,效能成為一個問題。我們的程式碼中有onScroll事件,其中包含querySelectorAll呼叫。即使呼叫被限制速率,如果您滾動到足夠遠的位置,頁面也會崩潰,此時將有太多調用迭代太多元素,瀏覽器無法跟上。 DOM的大小在這種用例中是相關的,因此在無限滾動頁面上運行的程式碼中,更傾向於使用getElement*呼叫。

    回覆
    0
  • P粉238355860

    P粉2383558602023-08-22 16:58:04

    語法和瀏覽器支援。

    querySelector在你想要使用更複雜的選擇器時更有用。

    例如,所有從屬於foo類別的元素的列表項目:.foo li

    #

    :字元在選擇器中有特殊意義。你需要對它進行轉義。 (選擇器轉義字元在JS字串中也有特殊意義,所以你也需要轉義)。

    document.querySelector("#view\:_id1\:inputText1")

    回覆
    0
  • 取消回覆