先序遍歷DOM樹的5種方法

来源:http://www.cnblogs.com/tracylin/archive/2016/02/26/5220867.html
-Advertisement-
Play Games

DOM樹由文檔中的所有節點(元素節點、文本節點、註釋節點等)所構成的一個樹結構,DOM樹的解析和構建是瀏覽器要實現的關鍵功能。既然DOM樹是一個樹結構,那麼我們就可以使用遍歷樹結構的相關方法來對DOM樹進行遍歷,同時DOM2中的"Traversal"模塊又提供了兩種新的類型,從而可以很方便地實現DO...


DOM樹由文檔中的所有節點(元素節點、文本節點、註釋節點等)所構成的一個樹結構,DOM樹的解析和構建是瀏覽器要實現的關鍵功能。既然DOM樹是一個樹結構,那麼我們就可以使用遍歷樹結構的相關方法來對DOM樹進行遍歷,同時DOM2中的"Traversal"模塊又提供了兩種新的類型,從而可以很方便地實現DOM樹的先序遍歷。

註:本文中的5種方法都是對DOM的先序遍歷方法(深度優先遍歷),並且只關註Element類型。

1. 使用DOM1中的基礎介面,遞歸遍歷DOM樹

DOM1中為基礎類型Node提供了一些api,通過這些api可以完成一些基礎的DOM操作。使用遞歸遍歷DOM樹的代碼比較簡單,核心思想就是先處理當前節點,然後再從左到右遞歸遍歷子節點,代碼如下:

  /**
     * 使用遞歸的方式先序遍歷DOM樹
     * @param node  根節點
     */
    function traversal(node){
        //對node的處理
        if(node && node.nodeType === 1){
            console.log(node.tagName);
        }
        var i = 0, childNodes = node.childNodes,item;
        for(; i < childNodes.length ; i++){
            item = childNodes[i];
            if(item.nodeType === 1){
                //遞歸先序遍歷子節點
                traversal(item);
            }
        }
    }

2. 使用DOM1的基礎介面,迭代遍歷DOM樹

與第1種方法不同,這一次使用迭代的方法遍歷DOM樹。使用迭代遍歷DOM樹相對複雜一些,關鍵點在於使用一個棧來維護節點的訪問路徑,當處理完當前節點時,先把該節點的第一個Element子節點作為下一次迴圈的根節點,並且按照從右到左的順序,將當前節點的其他子元素節點壓入棧中。如果當前節點沒有一個Element子節點,則從棧中彈出一個Element節點作為下一次迴圈的根節點,直到取不到根節點為止。代碼如下:

    /**
     * 使用迭代的方式先序遍歷DOM樹
     * @param node  根節點
     */
    function traversalIteration(node){
        var array = [], i = 0,k = 0,elementCount = 0, len = 0, childNodes,item;
        while(node != null){
            console.log(node.tagName);
            childNodes = node.childNodes;
            len = node.childNodes.length;
            elementCount = 0;
            if(len > 0){
                for(i = 0; i < len; i++){
                    item = childNodes[i];
                    if(item.nodeType === 1){
                        elementCount++;
                        node = item;
                        break;
                    }
                }
                for(k = len -1 ; k > i; k--){
                    item = childNodes[k];
                    if(item.nodeType == 1){
                        elementCount++;
                        array.push(item);
                    }
                }
                if(elementCount < 1){
                    node = array.pop();
                }
            }else{
                node = array.pop();
            }
        }
    }

3. 使用DOM擴展的Element Traversal API,遞歸遍歷DOM樹

DOMElement Traversal API提供了幾個方便DOM遍歷的介面,從而可以更加方便地取得一個節點的Element子節點。在《DOM擴展:DOM API的進一步增強[總結篇-上]》的第2節介紹了DOM擴展的Element Traversal API。代碼如下:

    /**
     * 使用DOM擴展的Traversal API提供的新的介面先序遍歷DOM樹
     * @param node 根節點
     */
    function traversalUsingTraversalAPI(node){
        if(node && node.nodeType === 1){
            console.log(node.tagName);
        }
        var i = 0,len = node.childElementCount, child = node.firstElementChild;
        for(; i < len ; i++){
            traversalUsingTraversalAPI(child);
            child = child.nextElementSibling;
        }
    }

4. 使用NodeIterator

DOM2的"Traversal"模塊提供了NodeIterator類型,使用它可以很方便地實現DOM樹的先序遍歷,《JavaScript高級程式設計第三版》的12.3.1節介紹了這個類型,我們這裡直接給出代碼如下:

    /**
     * 使用DOM2的"Traversal"模塊提供的NodeIterator先序遍歷DOM樹
     * @param node  根節點
     */
    function traversalUsingNodeIterator(node){
        var iterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT,null,false);
        var node = iterator.nextNode();
        while(node != null){
            console.log(node.tagName);
            node = iterator.nextNode();
        }
    }

5. 使用TreeWalker

TreeWalker類型可以說是NodeIterator類型的增強版,《JavaScript高級程式設計第三版》的12.3.2節介紹了這個類型,我們這裡也直接給出代碼如下:

    /**
     * 使用DOM2的"Traversal"模塊提供的TreeWalker先序遍歷DOM樹
     * @param node  根節點
     */
    function traversalUsingTreeWalker(node){
        var treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT,null,false);
        if(node && node.nodeType === 1){
            console.log(node.tagName);
        }
        var node = treeWalker.nextNode();
        while(node != null){
            console.log(node.tagName);
            node = treeWalker.nextNode();
        }
    }

歡迎小伙伴評論交流~~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 針對underscore.js封裝的方法進行具體的分析
  • 1 $("#jqGridId").setGridParam({url:"數據查詢地址"}).trigger("reloadGrid");
  • 首先Ajax的不刷新頁面提交數據,現在應用非常廣泛,廢話不多說馬上進主題!! 基本上瀏覽器能接收的信息,Ajax都可以接收,ex:字元串,html標簽,css標簽,xml格式內容,json格式內容等等..... <script> // IE瀏覽器 if(ActiveXObject){ // 微軟目前
  • JS中function的一些淺見
  • 今天總結了下Node.js的Formidable模塊的使用,下麵做一些簡要的說明。 1) 創建Formidable.IncomingForm對象 var form = new formidable.IncomingForm() 2) form.encoding = 'utf-8' 設置表單域的編碼
  • 1. 首先嘛,你得在瀏覽器里輸入要網址: 2. 瀏覽器查找功能變數名稱的IP地址 導航的第一步是通過訪問的功能變數名稱找出其IP地址。DNS查找過程如下: 瀏覽器緩存 – 瀏覽器會緩存DNS記錄一段時間。 有趣的是,操作系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘
  • 表格示例 <div ng-app="myApp" ng-controller="customersCtrl"> <table> <tr ng-repeat="x in names | orderBy : 'Country'"> <td>{{ $index + 1 }}</td> <td ng-if=
  • html5功能強大,數字和顏色輸入框例子 效果:http://hovertree.com/code/html5/rxujb6g8.htm 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="te
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...