首頁 > 軟體

JavaScript DOM API的使用教學及綜合案例

2023-03-19 06:02:25

一. 什麼是DOM

JavaScript主要由ECMAScript, DOM, BOM這三部分組成; 我們要知道要完成一個程式, 光有語法是遠遠不夠的, 對於JS來說, 除JS語法(ES)外, 還需要掌握一些WebAPI, 這些API是瀏覽器給JS程式碼提供的功能, 即DOM和BOM; DOM是頁面檔案物件模型, 可以對頁面中的元素進行操作, 而BOM是瀏覽器物件模型, 可以對瀏覽器視窗進行操作; 本篇部落格中主要介紹的就是DOM.

DOM 全稱為 Document Object Model, 是頁面檔案物件模型, html中的每個標籤都是可以對映到JS中的一個物件中的, 標籤中的內容都可以通過JS物件感知到, JS物件修改對應的屬效能夠影響到標籤的展示, 通過這樣的DOM API就可以讓JS程式碼來操作頁面元素.

二. 最常用的DOM API

1. 選中頁面元素

在DOM中, 任何一個頁面, 都會有一個document物件, 是頁面的一個全域性物件, 所有的DOM API都是通過document物件類展開的, 其中document物件中的querySelectorquerySelectorAll函數可以用來選擇元素, 通過傳入CSS選擇器來達到目的, 選擇的範圍是位於該函數之前所存在的選擇器, 沒找到返回值為null.

let obj = document.querySelector('選擇器');

要注意使用querySelector函數如果符合選擇的標籤在頁面中有多個, 就只會選擇在頁面中第一次出現的標籤.

如果想把符合選擇的元素都選中就需要使用querySelectorAll函數了, 在使用上和和querySelector 是一樣的.

let elem = document.querySelectorAll('選擇器');

使用該函數會返回一個類似於陣列的物件, 用法和陣列相同.

將得到的陣列物件裡面的元素展開檢視, 會發現有很多的屬性, 這些屬性都是DOM原生的一些屬性.

2. 操作元素的屬性

2.1 事件概念

JS要構建動態頁面, 就需要感知到使用者的行為, 而 “事件” 就是針對使用者的操作進行的一些響應, 比如滑鼠點選, 滑鼠移動, 鍵盤輸入, 調整瀏覽器視窗這些都是使用者的操作, 而程式碼就需要根據這些事件做出相應的響應.

事件的三要素:

  • 事件源, 哪個HTML元素產生的事件.
  • 事件型別, 比如滑鼠點選, 滑鼠移動, 鍵盤輸入等.
  • 事件處理程式, 當事件發生之後, 要執行哪個程式碼.

前端頁面中, 針對不同的事件也是有不同的處理方式的, 而處理方式都是再最開始的時候就設定好的(事件繫結).

看下面的這一行程式碼就是直接在元素標籤中使用onXXX這樣的屬性來繫結一個事件處理程式, onclick是一個描述處理滑鼠點選的事件.

<button onclick="alert('hello')">點一下試試</button>

如果事件處理的程式碼比較多的話使用上面這種寫法就不太合適了, 所以更推薦的是下面這種寫法, 可以直接使用onXXX這樣的方法進行繫結, 效果和上面是一樣的.

<script !src="">
    let button = document.querySelector("button");
    button.onclick = function (){
        alert("hello");
    }
</script>
<button onclick="alert('hello')">點一下試試</button>

當然,這裡的JS程式碼如果是寫在一個單獨的JS檔案中就更好了, 但本篇中的示範程式碼都比較簡單, 就使用內嵌式的寫法來引入JS程式碼了.

2.2 獲取/修改元素內容

在選中元素後, 就可以使用innerHTML屬性來獲取/修改一個標籤裡面的內容了.

//1.選中標籤
let var_name = document.querySelector();
//2.獲取內容
let content = var_name.innnerHTML;
//3.修改內容
var_name.innerHTML = '修改值';

程式碼範例, 將點選按鈕和輸出div中的內容繫結.

<div> hello world</div>
<button>點一下試試</button>-->
<script>
    let but = document.querySelector('but');
    but.onclick = function () {
        let div = document.querySelector('div');
        console.log(div.innerHTML);
    }
</script>

觀察控制檯的結果, 控制檯中多次點選按鈕的結果都被摺疊輸出了, 這是因為chrome控制檯會預設把相鄰且相同的紀錄檔進行合併, 另外再顯示一個數位表示輸出的次數, 我們可以點選開發者工具的設定欄, 設定一下讓它不合並就行了.

還要注意的是, 通過innerHTML是可以獲取到div內部的html結構的, 比如下面的的程式碼, 會將div標籤中的html程式碼也獲取到, 而innerText只能獲取文字內容, 並不能獲取html結構, innerHTML用的場景是要比innerText更多的.

<div>
    <span>hello world</span>
    <span>hello world</span>
</div>
<button class="but">點一下試試</button>
<script>
    let but = document.querySelector('.but');
    but.onclick = function () {
        let div = document.querySelector('div');
        console.log(div.innerHTML);
    }
</script>

修改元素也是一樣的操作, 比如將上面程式碼中的div中的內容修改為一個標題.

<div>
    <span>hello world</span>
    <span>hello world</span>
</div>
<button class="but">點一下試試</button>
<script>
    let but = document.querySelector('.but');
    but.onclick = function () {
        let div = document.querySelector('div');
        div.innerHTML = '<h1>這是一個一級標題</h1>>';
        console.log(div.innerHTML)
    }
</script>

計數器

有了上面的獲取和修改元素的知識, 我們這裡實現一個簡單的計數器, 就是點選一下按鈕, 計數器就+1.

實現思路也很簡單, 使用者的點選操作, 就會觸發點選事件, 就是先獲取到計數元素中的內容, 然後將元素內容進行加一操作再寫回元素中, 程式碼如下:

<div id='count'>0</div>
<button id='countAdd'>計數器:點選+1</button>
<script !src="">
    let counterAdd = document.querySelector('#countAdd');
    counterAdd.onclick = function () {
        let num = document.querySelector('#count');
        numAdd = parseInt(num.innerHTML) + 1
        num.innerHTML = numAdd;
    };
</script>

這個程式碼要注意的是, num.innerHTML這裡拿到的元素內容是字串型別的, 直接進行加法運算就是字串拼接的效果了, 而要完成算數相加的效果就需要將字串轉換為整數, 和Java中類似, 可以使用parseInt方法將字串轉換為整數, 而如果是浮點數就使用parseFloat方法

2.4 獲取/修改元素屬性

點選圖片切換

上面介紹的是修改元素(標籤)中的內容, 我們還可以在程式碼中使用DOM直接獲取元素的屬性並修改元素的屬性, 比如這裡實現一個效果, 就是點選一個圖片就可以切換到另一張圖片, 然後再點選就能再切換回來, 這個案例我們只需要設定點選事件為修改圖片的路徑即可, 也就是修改src屬性.

程式碼如下:

這裡要注意圖片的路徑儘量不要設定成中文的, 中文路徑在瀏覽器中涉及跳脫重新編碼的問題, 跳脫後路徑就可能沒有中文字元了, 判斷就可能出問題了.

<style>
    img {
        height: 500px;
    }
</style>
<img src="./man.jpg" alt="">
<script !src>
    let img = document.querySelector("img");
		console.dir(img);
    img.onclick = function() {
        if (img.src.indexOf('wo') !== -1) {
            img.src = './man.jpg';
        } else {
            img.src = './woman.jpg';
        }
    }
</script>

一個標籤中具體有哪些屬性可以修改, 可以使用console.dir()函數來獲取DOM API能夠操作的全部屬性, 比如img元素.

2.5 獲取/修改表單元素屬性

這裡把表單元素單拎出來是因為, 是因為, 表單元素中有一些特別的屬性是普通標籤沒有的, 主要需要區別的是一些表單元素想要獲取其中使用者輸入的內容的話是不能通過innerHTML拿到的, 這是因為input, textarea… 這些標籤元素都是單標籤, 是沒有內容的, 正確的獲取/修改的方式應該是通過這些標籤的value屬性來進行.

表單計數器

比如input標籤, 還是在文字方塊中實現一下計數功能, 同樣的要注意拿到的value屬性的值也是字串型別的, 要注意進行型別轉換.

<input type="text" value="0" id='count'>
<button id='countAdd'>計數器: 點選+1</button>
<script !src="">
    let counterAdd = document.querySelector('#countAdd');
    counterAdd.onclick = function () {
        let num = document.querySelector('#count');
        numAdd = parseInt(num.value) + 1
        num.value = numAdd;
    };
</script>

再舉例一個比較常見的場景, 我們平常見的登入功能中密碼框中的文字可以選擇是否顯示密碼, 這個實現起來其實也很簡單, 通過DOM來修改type屬性的值即可.

<input type="text" id="pw">
<button>隱藏密碼</button>
<script !src="">
    let pw = document.querySelector('#pw');
    let button = document.querySelector('button');
    button.onclick = function() {
        if (pw.type == 'text') {
            pw.type = 'password';
            button.innerHTML = '顯示密碼';
        } else {
            pw.type = 'text';
            button.innerHTML = '隱藏密碼';
        }
    }
</script>

全選/取消全選按鈕

這裡再實現一下全選功能, 也就是有若干個核取方塊, 點選全選按鈕, 就會選中所有的選項, 但只要某個選項取消, 則自動取消全選按鈕的勾選狀態.

實現的基本思路如下:

  1. 獲取全選按鈕元素, 獲取其按鈕元素
  2. 註冊全選按鈕的點選事件, 點選全選按鈕時, 全選按鈕的checked屬性發生改變, 將checked屬性值賦值給其他按鈕的checked屬性即完成了全選.
  3. 對每一個其他核取按鈕設定點選事件, 並將狀態與全選按鈕關聯, 即檢查其他核取按鈕是否選中, 如果選中, 則全選按鈕也選中(修改checked值為true), 否則全選按鈕不選中(修改checked值為false).
  4. 每次點選其他框都要檢測其他框是否都選中, 以確定全選按鈕的狀態.
<input type="checkbox" id="all">我全都要 <br>
    <input type="checkbox" class="girl">貂蟬 <br>
    <input type="checkbox" class="girl">小喬 <br>
    <input type="checkbox" class="girl">安琪拉 <br>
    <input type="checkbox" class="girl">妲己 <br>
    <script>
        //checked屬性為checked/true表示選中狀態,為空字串/false表示未選中
        //獲取到元素
        let all = document.querySelector('#all');
        let girls = document.querySelectorAll('.girl');
        //給all註冊點選事件,選中/取消所有選項
        all.onclick = function () {
            for (let i = 0; i < girls.length; i++) {
                //使girl元素狀態與all相同
                girls[i].checked = all.checked;
            }
        }
        //給所有girl元素註冊點選事件
        for (let i = 0; i < girls.length; i++) {
            girls[i].onclick = function () {
                //檢測當前是不是所有的girl元素都被選中了,確定all的狀態
                all.checked = checkGirls(girls);
            }
        }
        //實現checkGirls,檢測當前是不是所有的girl元素都被選中了
        function checkGirls(girls) {
            for (let i = 0; i < girls.length; i++) {
                if (!girls[i].checked) {
                    //只要一個 girl 沒被選中,就認為結果是 false(找到了反例)
                    return false;
                }
            }
            // 所有 girl 中都沒找到反例, 結果就是全選中
            return true;
        }
    </script>

2.6 獲取修改樣式屬性

第一種方式是通過修改元素的內聯樣式, 即修改元素的style屬性的值來指定樣式, 這種方式的優先順序很高, 適用於該樣式比較少的情況.

點選文字放大

文字放大效果的實現, 我們可以給文字所在的標籤註冊一個點選事件, 每點選一次就將字型大小增大, 即修改CSS的font-size屬性; 思路很簡單, 但JS程式碼的寫法上有一些細節需要注意, 在CSS中是不區分大小寫的, 且在CSS中不需要進行算數運算, 屬性和變數名是採用的是脊柱式命名法, 但-在JS中就不能用於命名了, 所以JS中採用駝峰命名的形式來表示CSS的屬性, 比如font-size屬性在對應JS的中就為fontSize了.

<div style="font-size:20px;">
    這是一段文字,點選之後字型放大
</div>
<script !src="">
    let div = document.querySelector("div");
    div.onclick = function() {
        //1.獲取文字大小屬性
        let size = parseInt(div.style.fontSize);
        console.log("修改前" + size);
        //2.修改文字大小
        size += 5;
        //3.寫回到屬性
        div.style.fontSize = size + "px";
        console.log("修改後" + size);
    }
</script>

還有一種修改樣式的方式可以通過修改類屬性來達到修改樣式的效果, 可以通過元素.className來獲取/修改類屬性的值, 由於class是 JS 的保留字, 所以這裡獲取類屬性的名字叫做className.

實現夜間/日間模式的切換

實現點選介面, 切換日間模式和夜間模式

<div class="container light">
    這是一大段話. <br>
    這是一大段話. <br>
    這是一大段話. <br>
    這是一大段話. <br>
</div>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    html, body {
        width: 100%;
        height: 100%;
    }
    .container {
        width: 100%;
        height: 100%;

    }
    .light {
        background-color: #f3f3f3;
        color: #333;
    }
    .dark {
        background-color: #333;
        color: #f3f3f3;
    }
</style>
<script !src="">
    let div = document.querySelector('div');
    div.onclick = function () {
        console.log(div.className);
        if (div.className.indexOf('light') != -1) {
            div.className = 'container dark';
        } else {
            div.className = 'container light';
        }
    }
</script>

3. 操作頁面節點

上述涉及的操作都是針對頁面已有的元素進行操作的, 利用DOM API還可以完成新增/刪除元素的操作.

3.1 新增節點

新增元素主要有兩個步驟, 首先需要建立一個新的建立元素節點, 然後把這個元素節點插入到父元素中就能完成元素的的新增(依賴於DOM樹).

可以使用creatElement方法來建立一個新的元素:

let element = document.createElement('元素標籤名');

插入到DOM樹中:

父元素.appendChild(建立的子元素);

程式碼範例:

關於插入節點還可以使用insertBefore將節點插入到指定節點之前.

新插入節點的父元素.insertBefore(新插入的元素, 指定節點(將要插在這個節點之前));
<div class="container">
    <div>11</div>
    <div>22</div>
    <div>33</div>
    <div>44</div>
</div>
<script>
    var newDiv = document.createElement('div');
    newDiv.innerHTML = '我是新的節點';
    var container = document.querySelector('.container');
    console.log(container.children);
    //children可以返回父元素所有的直系子節點的集合
    container.insertBefore(newDiv, container.children[0]);
</script>

3.2 刪除節點

刪除節點操作就很簡單了, 語法如下:

父元素.removeChild(需要刪除的子元素);

程式碼範例, 比如刪除上面程式碼無序列表中的33這個元素.

三. 綜合案例

1. 猜數位

目標頁面如下, 系統可以自動生成[1, 100]之間的亂數, 使用者輸入猜測數位, 能夠提示使用者數位是猜大了還是猜小了.

這裡的邏輯很簡單就不做過多的贅述了, 最關鍵的是JS中亂數的獲取, 我們可以通過Math.random()函數來獲取亂數, 該函數生成亂數的範圍是[0,1)區間內的一個小數, 我們需要的是[1,100]之間的整數, 我們可以乘上100後再拿到整數部分+1就能得到目標區間的數了.

<button id="flash">重開一局</button>
<div>請輸入要猜的數位</div>
<input type="text">
<button id="submit">提交</button>
<!--使用這個div來顯示猜測結果-->
<div class="result"></div>

<script>
  //1.生成一個1-100隨機的整數
  let toGuess = parseInt(100 * Math.random()) + 1;
  console.log(toGuess);//用於測試,方便檢視猜測結果
  //2.進行猜數位操作,比較使用者輸入的數和生成的亂數
  let input = document.querySelector('input');
  let resultDiv = document.querySelector('.result');
  let submit = document.querySelector('#submit');
  submit.onclick = function() {
    //取出輸入框中的內容
    if (input.value == '') {
      //輸入框沒有值,使用者啥都沒輸入,直接返回
      return;
    }
    let inputNum = parseInt(input.value);
    //比較大小關係
    if (inputNum < toGuess) {
      //小了
      resultDiv.innerHTML = '猜小了';
    } else if (inputNum > toGuess) {
      //大了
      resultDiv.innerHTML = '猜大了';
    } else {
      //猜對了
      resultDiv.innerHTML = '猜對了';
    }
  }
  //3.重新整理頁面
  let flash = document.querySelector('#flash');
  flash.onclick = function() {
    location.reload();
  }
</script>

實際效果:

2. 表白牆

目標頁面如下, 點選提交, 能夠把使用者輸入的話, 顯示在頁面中, 點選復原, 能夠撤回最後一條顯示在頁面的話.

這個案例也沒有難點, 只是的的揉合東西更多了一些, 前端頁面是通過HTML加上CSS彈性佈局實現的, 互動通過JavaScript DOM實現.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表白牆</title>
    <style>
        * {
            /* 消除瀏覽器的預設樣式 */
            margin: 0;
            padding: 0;
            /* 保證盒子不被撐大 */
            box-sizing: border-box;
        }

        .container {
            width: 600px;
            margin: 20px auto;
        }

        h1 {
            text-align: center;
        }

        p {
            text-align: center;
            color: #666;
            margin: 20px 0;
        }

        .row {
            /* 開啟彈性佈局 */
            display: flex;
            height: 40px;
            /* 水平方向居中 */
            justify-content: center;
            /* 垂直方向居中 */
            align-items: center;
        }

        .row span {
            width: 80px;
        }

        .row input {
            width: 200px;
            height: 30px;
        }

        .row button {
            width: 280px;
            height: 30px;
            color: white;
            background-color: orange;
            /* 去掉邊框 */
            border: none;
            border-radius: 5px;
        }

        /* 點選的時候有個反饋 */
        .row button:active {
            background-color: grey;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>表白牆</h1>
        <p>輸入內容後點選提交, 資訊會顯示到下方表格中</p>
        <div class="row">
            <span>是誰: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>對誰: </span>
            <input type="text">
        </div>
        <div class="row">
            <span>說: </span>
            <input type="text">
        </div>
        <div class="row">
            <button id="submit">提交</button>
        </div>
        <div class="row">
            <button id="revert">復原</button>
        </div>
        <!-- <div class="row">
            xxx 對 xx 說 xxxx
        </div> -->
    </div>

    <script>
        // 實現提交操作. 點選提交按鈕, 就能夠把使用者輸入的內容提交到頁面上顯示.
        // 點選的時候, 獲取到三個輸入框中的文字內容
        // 建立一個新的 div.row 把內容構造到這個 div 中即可.
        let containerDiv = document.querySelector('.container');
        let inputs = document.querySelectorAll('input');
        let button = document.querySelector('#submit');
        button.onclick = function() {
            // 1. 獲取到三個輸入框的內容
            let from = inputs[0].value;
            let to = inputs[1].value;
            let msg = inputs[2].value;
            if (from == '' || to == '' || msg == '') {
                return;
            }
            // 2. 構造新 div
            let rowDiv = document.createElement('div');
            rowDiv.className = 'row message';
            rowDiv.innerHTML = from + ' 對 ' + to + ' 說: ' + msg;
            containerDiv.appendChild(rowDiv);
            // 3. 清空之前的輸入框內容
            for (let input of inputs) {
                input.value = '';
            }
        }
        let revertButton = document.querySelector('#revert');
        revertButton.onclick = function() {
            // 刪除最後一條訊息.
            // 選中所有的 row, 找出最後一個 row, 然後進行刪除
            let rows = document.querySelectorAll('.message');
            if (rows == null || rows.length == 0) {
                return;
            }
            containerDiv.removeChild(rows[rows.length - 1]);
        }
    </script>
</body>
</html>

實際效果:

總結 

到此這篇關於JavaScript DOM API的使用教學及綜合案例的文章就介紹到這了,更多相關JavaScript DOM API使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com