zishu's blog

zishu's blog

一个热爱生活的博主。https://zishu.me

DOM--文檔對象模型

DOM 中文名文檔對象模型,英文名 Document Object Model,我們簡稱為 DOM,是針對 html 和 xml 文檔的一種 API,將 html 以一種樹狀結構呈現出來,可以更直觀去研究文檔結構,我們將這種樹狀文檔結構稱為--DOM 樹,或者節點樹,一樣的概念

一、什麼是 DOM?#

DOM 中文名文檔對象模型,英文名 Document Object Model,我們簡稱為 DOM,是針對 html 和 xml 文檔的一種 API,將 html 以一種樹狀結構呈現出來,可以更直觀去研究文檔結構,我們將這種樹狀文檔結構稱為--DOM 樹,或者節點樹,一樣的概念

js 通過 dom 節點,可以對文檔的 html 標籤,屬性,css 樣式,以及具體的內容做出修改,並對頁面中的所有事件進行響應

dom 樹結構圖

二、節點樹#

1. 節點類型#

  1. 文檔節點--Document
  2. 標籤節點--Element
  3. 文本節點--Text
  4. 註釋節點--Comment
  5. 屬性節點--Attr

2. 屬性#

  1. 節點類型--nodeType
  2. 節點名稱--nodeName
  3. 節點值--nodeValue
  4. 子節點--childNodes
  5. 父節點--parentNodes
  6. 上一個節點--previousSibling
  7. 下一個節點--nextSibling
  8. 第一個子節點--firstChild
  9. 最後一個子節點--lastChild

3. 文檔節點--document#

(1) 獲取#

  1. getElementById ()--通過 id 獲取元素
<div id="demo">通過id獲取元素</div>

<script>
    var demo = document.getElementById('demo');
    demo.onclick = function() {
        console.log('通過id獲取元素')
    }
</script>

<!-- 點擊id為demo的元素,控制台輸出'通過id獲取元素' -->
  1. getElementsByName ()--通過 name 獲取元素
<input type="text" name="int" value="通過name獲取元素1">
<input type="text" name="int" value="通過name獲取元素2">

<script>
    var int = document.getElementsByName('int');
    for(var i = 0;i < int.length; i++) {
        console.log(int[i].value);
    }
</script>

<!-- 控制台輸出name為int的元素的value值 -->
  1. getElementsByTagName ()--通過標籤名獲取元素
<div>通過標籤名獲取元素1</div>
<div>通過標籤名獲取元素2</div>

<script>
    var div = document.getElementsByTagName('div');
    for(var i = 0;i < div.length; i++) {
        console.log(div[i].innerHTML)
    }
</script>

<!-- 控制台輸出標籤名為div的元素的文本內容 -->
  1. getElementsByClassName ()--通過 class 獲取元素
<div class="demo">通過class獲取元素1</div>
<div class="demo">通過class獲取元素2</div>

<script>
    var demo = document.getElementsByClassName('demo');
    for(var i = 0;i < demo.length; i++) {
        console.log(demo[i].innerHTML)
    }
</script>

<!-- 控制台輸出class為demo的元素的文本內容 -->
  1. querySelector ()--通過選擇器獲取元素

querySelector () 括號裡面要跟上符號,class就寫.id就寫#標籤直接寫標籤名TagName

<div>通過選擇器獲取標籤名</div>
<div class="div">通過選擇器獲取class</div>
<div id="div">通過選擇器獲取id</div>

<script>
    var divtag = document.querySelector('div');
    var divclass = document.querySelector('.div');
    var divid = document.querySelector('#div');

    divtag.onclick = function() {
        console.log('通過選擇器獲取標籤名')
    };
    // 點擊標籤div,控制台輸出"通過選擇器獲取標籤名"

    divclass.onclick = function() {
        console.log('通過選擇器獲取class')
    };
    // 點擊class為div,控制台輸出"通過選擇器獲取class"

    divid.onclick = function() {
        console.log('通過選擇器獲取id')
    };
    // 點擊id為div,控制台輸出"通過選擇器獲取id"
</script>
  1. querySelectorAll ()--通過選擇器獲取元素集合

獲取的是一個數組集合

<input type="text" value="int1">
<input type="text" value="int2">
<input type="text" value="int3">

<script>
    var int = document.querySelectorAll('input')
    for(i = 0; i < int.length; i++) {
        console.log(int[i].value)
    }
</script>

<!-- 瀏覽器依次打印出`int1`,`int2`,`int3` -->

(2) 創建#

  1. createElement ()--創建元素(標籤)節點
<ul id="ul"></ul>

<script>
    var ul = document.getElementById('ul');
    ul.appendChild(document.createElement('li'))
</script>

可以看到,ul 下面已經生成了一個 li 標籤

image

  1. createTextNode ()--創建文本節點
<ul id="ul"></ul>

<script>
    var ul = document.getElementById('ul');
    var li = ul.appendChild(document.createElement('li'));
    var node = document.createTextNode('我是li');
    li.appendChild(node);
</script>

li 標籤中生成了一段文本

image

  1. createAttribute ()--創建屬性節點
<input type="text">

<script>
    var int = document.getElementsByTagName('input')[0];
    var value = document.createAttribute('value');
    value.nodeValue = '通過創建屬性節點生成';
    int.setAttributeNode(value);
</script>

可以看到 value 屬性值被成功創建

image

  1. createComment ()--創建註釋節點
<div id="div">創建一個註釋節點</div>

<script>
    var div = document.getElementById('div');
    var comment = document.createComment('添加一個註釋節點');
    div.appendChild(comment);
</script>

f12 查看源碼,可以看到 div 生成一行註釋

image

  1. createDocumentFragment ()--創建文檔片段

文檔片段的作用,就相當於添加的所有的節點的父元素

1. 假如沒有 createDocumentFragment,添加了很多節點,也可以在 dom 上呈現,但是每次添加的時候都會調用一次 appendChild () 方法,產生很多次頁面渲染,顯得比較臃腫
2. 把多次添加的節點放在一個 createDocumentFragment 節點裡面,頁面只會調用一次就可以把所有的節點都渲染了

  1. createEvent ()--創建事件對象

  2. addEventListener ()--添加事件監聽函數

  3. removeEventListener ()--移除事件監聽函數

事件監聽函數詳解

  1. dispatchEvent ()--觸發事件

操作 css#

<div id="demo">dom</div>
<script>
    // 直接通過'.'來操作style
    var demo= document.getElementById('demo');
    demo.style.color = 'red';

    // 通過setAttribute()來創建屬性節點
    demo.setAttribute('style','background-color: green');

    // 通過style的cssText屬性
    demo.style.cssText = "border: 10px solid black";
</script>

4. 元素節點 (element 對象)#

image

有關 innerHTML, innerText, outerHTML, outerText 的區別

一個是元素內容,一個是文本內容

image

<div id="div1">第一個div</div>
<div id="div2">第二個div</div>
<div id="div3">第三個div</div>
<div id="div4">第四個div</div>
<div id="div5"></div>
<div id="div6"></div>
<div id="div7"></div>
<div id="div8"></div>
<script>
    var div1 = document.getElementById('div1').innerHTML
    console.log(div1)   // 第一個div

    var div1 = document.getElementById('div1').outerHTML
    console.log(div1)   // <div id="div1">第一個div</div>

    var div2 = document.getElementById('div2').innerText
    console.log(div2)   // 第二個div

    var div2 = document.getElementById('div2').outerText
    console.log(div2)   // 第二個div

    document.getElementById('div5').innerHTML = '<a>《第5個div》</a>'
    // 在原有的標籤內增加內容,如果有標籤會被識別

    document.getElementById('div6').outerHTML = '<a>《第6個div》</a>'
    // 原來的標籤會被覆蓋,新的文本中如果含有標籤會自動生成,如果沒有標籤則直接以文本形式展示

    document.getElementById('div7').innerText = '<a>《第7個div》</a>'
    // 在原有的標籤內增加內容,新標籤不會被識別為標籤元素,而是被當作文本內容直接寫入原標籤內

    document.getElementById('div8').outerText = '<a>《第8個div》</a>'
    // 原來的標籤會被覆蓋,新標籤不會被識別為標籤元素,而是直接被當作文本形式展示
</script>

(1) 節點屬性#

  1. childElementCount--返回當前元素的子節點的個數
<div id="demo">
    <a></a>
    <span></span>
    <p></p>
    <div></div>
</div>

<script>
    var demo = document.getElementById('demo')
    console.log(demo.childElementCount) // 4
</script>
  1. firstElementChild--返回當前元素的第一個子元素節點
    lastElementChild--返回當前元素的最後一個子元素節點
<div id="demo">
    <a></a>
    <span></span>
    <p></p>
    <div></div>
</div>

<script>
    var demo = document.getElementById('demo')
    console.log(demo.firstElementChild) // <a></a>
    console.log(demo.lastElementChild)  // <div></div>
</script>
  1. nextElementSibling--返回當前元素的下一個兄弟元素節點
    previousElementSibling--返回當前元素的上一個兄弟元素節點
<span></span>
<div id="demo"></div>
<p></p>

<script>
    var demo = document.getElementById('demo')
    console.log(demo.nextElementSibling)        // <p></p>
    console.log(demo.previousElementSibling)    // <span></span>
</script>
  1. 返回當前元素所有的子節點
<div id="demo">
    <span></span>
    <p></p>
    <a></a>
</div>


<script>
    var demo = document.getElementById('demo').children
    for(var i in demo) {
        console.log(demo[i])
    }
</script>

控制台查看返回結果

image

  1. 返回所有子節點集合
<div id="demo">
    <span></span>
    <p></p>
    <a id="demo1"></a>
</div>


<script>
    var demo = document.getElementById('demo').children
    for(var i in demo1.childNodes) {
        console.log(demo[i])
    }
</script>

image

(2) 節點方法#

  1. appendChild--插入子節點
<div id="demo"></div>
<script>
    var demo = document.getElementById('demo')
    var node = document.createTextNode('插入一個子節點')
    demo.appendChild(node)
</script>  

f12 可以看到,div 被插入了一個節點

image

  1. insertBefore (a, b)--在指定位置插入節點

參數 a 表示要插入的內容,b 表示定位,在 b 節點之前插入 a 節點

<div id="demo"></div>
<script>
    var demo = document.getElementById('demo')
    var node = document.createTextNode('插入一個子節點')
    demo.appendChild(node)

    var hr = document.createElement('hr')
    demo.insertBefore(hr, node)
</script>  

可以看到,原來的文本節點之前,被添加了一個新的元素節點

image

  1. replaceChild (a, b)--替換節點

用參數 a 替換參數 b,a 表示新節點,b 表示舊節點

<div id="demo"></div>
<script>
    var demo = document.getElementById('demo')
    var node = document.createTextNode('插入一個子節點')
    demo.appendChild(node)

    var h3 = document.createElement('h3')
    var h3node = document.createTextNode('title標題')
    h3.appendChild(h3node)
    demo.replaceChild(h3, node)
</script>  

h3是新節點,node是舊節點,根據圖片可以看到,b 替換掉了 a,成功上位

image

  1. removeChild--父節點刪除子節點
<div id="demo">
    <div id="son"></div>
</div>

<script>
    var demo = document.getElementById('demo')
    var son = document.getElementById('son')
    demo.removeChild(son)
</script>  

f12 可以看到,id 為 son 的元素節點,通過demo.removeChild()已經被刪除了

image

  1. removeAttribute--刪除屬性節點
<div id="demo" class="div"></div>

<script>
    var demo = document.getElementById('demo')
    demo.removeAttribute('class')
</script>  

class 屬性已經被刪除了

image

  1. 刪除文本節點
<div id="demo">文本</div>

<script>
    var demo = document.getElementById('demo')
    demo.removeChild(demo.childNodes[0])
</script>  

通過demo.childNodesp[0]獲取 demo 的第一個節點,即文本節點,然後removeChild它,就刪除了

image

  1. isEqualNode--判斷兩個元素是否相等
    isSameNode--判斷兩個元素是否相同

兩者分別代表相等相同

(1) isEqualNode相等,指的是兩個節點是否是同一類型,具有相等的屬性(包括:nodeName, nodeValue... 等等),還有相等的 attributes,childNodes(相等的位置包含相同的值)
(2) isSameNode相同,指的是兩個節點引用的是同一個對象

<form action="#">
    <input type="button" />
</form>

<form action="#">
    <input type="button" />
</form>

<form action="#" id="o">
    <input type="button" />
</form>

<form action="#" id="o">
    <input type="text" />
</form>

<script>
    var forms = document.forms;

    var form1 = forms[0];
    var form2 = forms[1];
    var form3 = forms[2];
    var form4 = forms[3];
    var _form1 = document.querySelectorAll('form')[0];


    console.log(form1.isSameNode(form1))  //true  兩個節點引用的對象都是第一個form
    console.log(form1.isSameNode(_form1)) //true  兩個節點引用的對象都是第一個form
    console.log(form1.isSameNode(form2))  //false 兩個節點引用的不是一個對象

    console.log(form1.isEqualNode(form2)) //true  兩個節點具有完全等同屬性
    console.log(form1.isEqualNode(form3)) //false form1中無等同的id屬性
    console.log(form3.isEqualNode(form4))  //fasle form4的childNodes中的input為text類別,與form3不同
</script>

根據例子代碼可以看出區別:

(1) isSameNode只有引用同一個對象時才相同,比如用兩中方法調用同一個對象,再比較這兩種方法,比來比去還是那個對象,所以相同
(2) 而isEqualNode比較兩個對象的元素節點是否相等,只要兩者一致就可以相等 true

  1. hasChildNodes ()--判斷一個元素是否擁有子節點

判斷demo是否擁有子節點,然後輸出他的子節點

<div id="demo">
    <!-- <a></a> -->
</div>

<script>
    var demo = document.getElementById('demo')
    console.log(demo.hasChildNodes())
    console.log(demo.childNodes)
</script>

image

  1. contains (a)--判斷一個節點是否包含指定子節點(參數 a 表示要判斷的子節點)

存在id="a"的元素,因此 contains 判斷成功輸出true

不存在id="b"的元素,因此輸出false

<div id="demo">
    <a id="a"></a>
    <a></a>
</div>

<script>
    var demo = document.getElementById('demo')
    var a = document.getElementById('a')
    console.log(demo.contains(a))   // true

    var b = document.getElementById('b')
    console.log(demo.contains(b))   // false
</script>

5. 屬性節點 (Attr 對象)#

<input type="text" id="int">

<script>
    var int = document.getElementById('int')

    // 1.獲取屬性值
    console.log(int.getAttribute("type"))   
    // text
    
    // 2.獲取屬性節點
    console.log(int.getAttributeNode("type"))
    // type="text"
    
    // 3.設置屬性值
    int.setAttribute("value", "input框")
    // <input type="text" id="int" value="input框">

    // 4.設置屬性節點
    let name = document.createAttribute("name");
    name.nodeValue = "uname";
    int.setAttributeNode(name);
    console.log(int.getAttributeNode('name').value) 
    // <input type="text" id="int" value="input框" name="uname">

    // 5.刪除屬性節點
    console.log(int.removeAttribute('name'))
    // <input type="text" id="int" value="input框">

    // 6.判斷是否存在屬性
    console.log(int.hasAttributes())
    // true

    // 7.判斷是否存在指定屬性
    console.log(int.hasAttribute('value'))
    // true
</script>

注意:hasAttributehasAttributes的區別
hasAttributes判斷是否存在屬性,
hasAttribute判斷是否存在指定屬性

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。