Mô hình DOM trong javascript

Giới thiệu về mô hình DOM

Khi trình duyệt đọc cấu trúc html của trang web, nó sẽ xây dựng nên một mô hình có thứ bậc phân cấp. Mô hình này diễn tả đúng cấu trúc html trong trang web. Mô hình này gọi là mô hình DOM.

Mô hình DOM là 1 trong các chuẩn của tổ chức W3C : webhere.vn/thiet-ke-web-chuan-w3c/. Nó quy định chung cho cách mà trình duyệt xây dựng cây phân.

Nhờ DOM, bạn dùng Javascript mới có thể:

  • Chỉnh nội dung các tag HTML trong trang
  • Chỉnh thuộc tính  các tag HTML trong trang
  • Chỉnh định dạng CSS các tag HTML trong trang
  • Xóa các tag và thuộc tính không mong muốn trong trang
  • Thêm các tag HTML mới vào trang
  • Tương tác với các sự kiện của các tag trong trang

Element /Node trong mô hình DOM

Các tag được gọi là Element hay Node trong DOM. Mỗi node có những thuộc tính và hàm riêng.
.

Cấu trúc mô hình DOM trong javascript và quan hệ giữa các node

<html>
    <head>
        <title>My Title</title>
    </head>
    <body>
        <a href="index.html">My link</a>
        <h1>My header</h1>
    </body>
</html>
mô hình dom
  • Node đầu tiên trong DOM được gọi là root (gốc), đó là node document
  • Giữa các node trong DOM có mối quan hệ cha, con và anh em (siblings).
  • Tất cả các node, ngoại trừ root chỉ có một cha
  • Một node có thể có nhiều con hoặc không có con nào
  • Node lá (leaf) không có con
  • Những node anh em (siblings) với nhau có cùng một cha.

Tóm lại, mô hình DOM trong javascript giống như một cái cây có gốc và nhiều cành nhánh. Gốc cây là node gốc và các cành nhánh là các node con cháu.

Các loại node/element của mô hình DOM trong javascript

Các loại node (node types) trong DOM bao gồm:

  1. Document: là node diễn tả toàn bộ tài liệu
  2. Elements: Node dạng này chính là các tag. Ví dụ br, img
  3. Comment: là node chứa các ghi chú trong tài liệu
  4. Attr:  Là node chứa thuộc tính của các tag
  5. Text : là node chứa chữ

Các hàm và thuộc tính của element/node

Theo mô hình DOM trong javascript , thì mỗi node có nhiều thuộc tính và nhiều hàm. Bạn có thể truy xuất tới các thuộc tính của node và gọi các hàm của node.

Property / Method Description
attributes Trả về 1 mảng là các thuộc tính của element
childElementCount Return the number of child elements an element has
childNodes Return a collection of an element’s child nodes (including text and comment nodes)
children Return a collection of an element’s child element(excluding text and comment nodes)
classList Returns the class name(s) of an element
className Sets or returns the value of the class attribute of an element
clientHeight Returns the height of an element, including padding
clientLeft Returns the width of the left border of an element
clientTop Returns the width of the top border of an element
clientWidth Returns the width of an element, including padding
contentEditable Sets or returns whether the content of an element is editable or not
firstChild Returns the first child node of an element
firstElementChild Returns the first child element of an element
id Gán hoặc trả về id của element
innerHTML Gán hoặc trả về code html trong element
innerText Gán hoặc trả về text trong element (không có code html)
lastChild Returns the last child node of an element
lastElementChild Returns the last child element of an element
nextSibling Returns the next node at the same node tree level
nextElementSibling Returns the next element at the same node tree level
nodeName Returns the name of a node
nodeType Returns the node type of a node
nodeValue Sets or returns the value of a node
offsetHeight Returns the height of an element, including padding, border and scrollbar
offsetWidth Returns the width of an element, including padding, border and scrollbar
offsetLeft Returns the horizontal offset position of an element
offsetParent Returns the offset container of an element
offsetTop Returns the vertical offset position of an element
outerHTML Sets or returns the content of an element (including the start tag and the end tag)
outerText Sets or returns the outer text content of a node and its descendants
parentNode Returns the parent node of an element
parentElement Returns the parent element node of an element
previousSibling Returns the previous node at the same node tree level
scrollHeight Returns the entire height of an element, including padding
scrollLeft Sets or returns the number of pixels an element’s content is scrolled horizontally
scrollTop Sets or returns the number of pixels an element’s content is scrolled vertically
style Sets or returns the value of the style attribute of an element
tagName Trả về tên tag của element
textContent Sets or returns the textual content of a node and its descendants
appendChild() Adds a new child node, to an element, as the last child node
click() Simulates a mouse-click on an element
blur() Removes focus from an element
contains() Returns true if a node is a descendant of a node, otherwise false
focus() Gives focus to an element
getAttribute() Returns the specified attribute value of an element node
getAttributeNode() Returns the specified attribute node
getBoundingClientRect() Returns the size of an element and its position relative to the viewport
getElementsByClassName() Returns a collection of all child elements with the specified class name
getElementsByTagName() Returns a collection of all child elements with the specified tag name
hasAttribute() Returns true if an element has the specified attribute, otherwise false
insertBefore() Inserts a new child node before a specified, existing, child node
setAttribute() Sets or changes the specified attribute, to the specified value
querySelector() Returns the first child element that matches a specified CSS selector(s) of an element
remove() Xóa 1 element khỏi DOM
removeAttribute() Removes a specified attribute from an element
removeChild() Removes a child node from an element

Truy cập đến node

Có thể truy cập đến các element/node bằng nhiều cách:

  • Sử dụng hàm getElementById(id) : Trả về node có thuộc tính id chỉ định
  • Sử dụng hàm getElementsByName(name): Trả về 1 mảng các node có name chỉ định
  • Sử dụng hàm getElementsByTagName(name):Trả về  1 mảngcác node có tên tag chỉ định
  • Sử dụng hàm getElementsByClassName(name):Trả về  1mảngcác node có class chỉ định
  • Ngoài ra có thể sử dụng mối quan hệ cha , con, láng giềng, trước sau giữa các node để truy cập

Một số thuộc tính thường dùng của element/node

x là 1 node trong DOM, bạn sẽ thường dùng các thuộc tính sau của x:

Thuộc tính Giải thích
x.innerHTML Mã html trong x
x.nodeName tên của x
x.nodeValue giá trị của x
x.nodeType kiểu của Node
x.parentNode Node cha của x
x.childNodes Các node con của x
x.attributes Các node thuộc tính của x

Ví dụ 1: Các loại hoa

<body>
<ul id="dsHoa" class="abc"><li>Hoa Hồng</li><li>Hoa Lan</li></ul><hr>
<script>
var h = document.getElementById("dsHoa");  //biến h là 1 node trong DOM
document.write("<p>Tên node: " + h.nodeName + "</p>");
document.write("<p>Giá trị của node: " + h.nodeValue + "</p>");
document.write("<p>Node cha: " + h.parentNode.nodeName + "</p>");
document.write("<p>Node con đầu tiên: " + h.firstChild.innerText + "</p>");
document.write("<p>Node con thu hai: " + h.childNodes[1].innerText+ "</p>");
document.write("<p>Node Type: " + h.nodeType+ "</p>");
document.write("<xmp>Mã html: " + h.innerHTML+ "</xmp>");
document.write("<p>Text : " + h.innerText+ "</p>");
console.log(h);
console.log(h.attributes);
console.log(h.childNodes);
h.childNodes[1].innerText = "Hoa Phượng";
h.firstChild.innerText = "Hoa Mai";
</script>
</body>

Ví dụ 2: Các lệnh get

<body>
    <h2 id="tp">THƠ HAY</h2>
    <h3 class="vt">CHA ĐÓ</h3>
    <p>Đường xa heo hút dặm ngàn<br>Đời cha vất vả gian nan thác ghềnh.</p>
    <p>Sông dài biển rộng trời cao.<br>Công Cha tôi cũng không sao sánh bằng. </p> 
    <h3 class="vt">MẸ ĐÂY</h3>
    <p name="c2"> Mẹ tôi hai tiếng thân thươnng<br/>Ôi hai tiếng ấy quý dường ngọc châu</p>
    <p> Mẹ ơi con chịu bao điều<br/> Nhưng không chịu nổi thân diều đứt dây</p>
    <hr>
    <h2>Bạn nhớ tới Mẹ khi nào:</h2>
    <input type="checkbox" name="me" value="1">Đói<br>
    <input type="checkbox" name="me" value="2">No<br>
    <input type="checkbox" name="me" value="3">Bệnh
    <hr>
</body>
<script>
    var x = document.getElementById('tp'); console.log(x.innerHTML);
    arr = document.getElementsByName("me"); console.log(arr);
    arr = document.getElementsByTagName("h2"); console.log(arr);
    arr = document.getElementsByClassName("vt"); console.log(arr);
</script>

Giá trị vài thuộc tính quan trọng:

Thuộc tính Của node Có giá trị là
nodeName element Tên thẻ HTML
attribute Tên thuộc tính
text #text
document #document
nodeValue element null
attribute Giá trị của thuộc tính
text Văn bản
nodeType element 1
attribute 2
text 3
comment 8
document 9

DOM Style

Theo quy định thì các node của mô hình DOM trong javascript, đều có đối tượng style để chứa các thông tin định dạng css. Thông qua đối tượng style này, bạn có thể định dạng hoặc định dạng lại các node. Cú pháp gán/truy xuất thuộc tính css thông qua DOM

x.style.tênthuộctính

Trong đó x là node bạn chọn để định dạng. Còn tenthuoctinh thì tra cứu trong bảng dưới. Sau đây là 1 số thuộc tính css thường dùng. Chú ý: 1 vài tên thuộc tính css trong đối tượng style có thể khác 1 chút với tên thuộc tính css chuẩn.

Property Description
background Sets or returns all the background properties in one declaration
backgroundColor Sets or returns the background-color of an element
backgroundImage Sets or returns the background-image for an element
border Sets or returns borderWidth, borderStyle, and borderColor in one declaration
borderRadius A shorthand property for setting or returning all the four borderRadius properties
bottom Sets or returns the bottom position of a positioned element
boxSizing Allows you to define certain elements to fit an area in a certain way
color Sets or returns the color of the text
display Sets or returns an element’s display type
cssFloat Sets or returns the horizontal alignment of an element
fontFamily Sets or returns the font family for text
fontSize Sets or returns the font size of the text
fontStyle Sets or returns whether the style of the font is normal, italic or oblique
height Sets or returns the height of an element
left Sets or returns the left position of a positioned element
letterSpacing Sets or returns the space between characters in a text
lineHeight Sets or returns the distance between lines in a text
margin Sets or returns the margins of an element (can have up to four values)
padding Sets or returns the padding of an element (can have up to four values)
position Sets or returns the type of positioning method used for an element (static, relative, absolute or fixed)
resize Sets or returns whether or not an element is resizable by the user
right Sets or returns the right position of a positioned element
textAlign Sets or returns the horizontal alignment of text
top Sets or returns the top position of a positioned element
width Sets or returns the width of an element
zIndex Sets or returns the stack order of a positioned element

Ngoài việc dùng đối tượng style để định dạng cho node, bạn cũng có thể định dạng cho node bằng cách gán cho thuộc tính className của node tên của class css đã tạo

Ví dụ: Dùng javascript định dạng phần tử

<style>.abc{ text-shadow: 3px 3px 1px fuchsia }</style>
<body>
    <h2 id="tp">THƠ HAY</h2>
    <h3 class="vt">CHA ĐÓ</h3>
    <p>Đường xa heo hút dặm ngàn<br>Đời cha vất vả gian nan thác ghềnh.</p>
    <p>Sông dài biển rộng trời cao.<br>Công Cha tôi cũng không sao sánh bằng. </p> 
    <h3 class="vt">MẸ ĐÂY</h3>
    <p name="c2"> Mẹ tôi hai tiếng thân thươnng<br/>Ôi hai tiếng ấy quý dường ngọc châu</p>
    <p> Mẹ ơi con chịu bao điều<br/> Nhưng không chịu nổi thân diều đứt dây</p>
    <hr>
    <h2>Bạn nhớ tới Mẹ khi nào:</h2>
    <input type="checkbox" name="me" value="1">Đói<br>
    <input type="checkbox" name="me" value="2">No<br>
    <input type="checkbox" name="me" value="3">Bệnh
    <hr>
</body>
<script>
    document.getElementById('tp').style.color='red';
    alert(document.getElementById('tp').style.color);
    document.getElementById('tp').style.backgroundColor='darkgray';
    document.getElementsByTagName('h2')[1].className='abc';
</script>

https://www.w3schools.com/jsref/dom_obj_style.asp

Thêm node vào DOM

Sử dụng hàm appendChild để thêm node.

Thêm text vào tag có sẵn

Tạo textnode

<button onclick="themtext()">Thêm text</button> <p id="doan1"></p>
<script>
function themtext() {
    var tn = document.createTextNode("Hãy tập sống thương yêu");
    var p = document.getElementById("doan1");
    p.appendChild(tn);
}
</script>

Thêm paragraph chứa text

Tạo textnode rồi tạo tag p, thêm textnode vào tag p rồi thêm tag p vào node cha

<button onclick="themtagp()">Thêm đoạn</button> <div id="txn"></div>
<script>
function themtagp() {
    var chu = document.createTextNode("Có rất nhiều niềm vui thanh tao");
    var tagp = document.createElement("p");
    tagp.appendChild(chu);
    document.getElementById("txn").appendChild(tagp);
}
</script>

Xóa node khỏi DOM

Muốn xóa node khỏi DOM, bạn dùng hàm removeChild

<ul id="thucung"> <li>Chó</li> <li>Mèo</li><li>Chim</li></ul>
<button onclick="abc()">Xóa mục đầu</button>
<script>
function abc() {
  var list = document.getElementById("thucung");
  list.removeChild(list.childNodes[0]);
}
</script>
<!-- Chú ý  <li> không có khoảng trắng ở đầu -->

Gán thuộc tính cho các node / element

Bạn dùng hàm setAttribute() để gán giá trị cho thuộc tính của node. Nếu node đã có thuộc tính thì giá trị của thuộc tính sẽ thay đổi, còn nếu node chưa có thuộc tính thì sẽ nó sẽ được thêm vào.

<button onclick="abc()">Gán thuộc tính</button><hr>
<input value="OK"> <br>
<button onclick="alert('Chúc an lành')" disabled="true">Xử lý </button><br>
<a href="http://google.com" id="tlw">Link</a><br>
<img src="https://longnv.name.vn/wp-content/uploads/2020/03/tong-quan-ve-javascript.png">
<script>
function abc() {
  document.getElementsByTagName("INPUT")[0].setAttribute("type", "button"); 
  document.getElementById("tlw").setAttribute("href", "https://longnv.name.vn");
  document.getElementsByTagName("img")[0].setAttribute("width", "200px");
  document.getElementsByTagName("button")[1].disabled=false;
}
</script>

Tham khảo thêm

https://www.w3schools.com/js/js_htmldom.asp
https://www.w3schools.com/whatis/whatis_htmldom.asp

Vì dụ tổng hợp: Chỉnh định dạng đối tượng

<style>
    #tbl { width: 4ppx; margin: auto; border-collapse: collapse;}
    #tbl td { border: 1px solid darkblue; padding: 4px;}
    h2, h3 { text-align: center;}
</style>
<h2>Thực tập : Chỉnh định dạng đối tượng</h2>
<table id="tbl"> 
    <tr id="dong1">
        <td>Dòng 1 - ô 1 </td>
        <td><span>Dòng 1 - <b>ô 2</b> </span></td>
        <td>Dòng 1 - ô 3 </td>
    </tr>
    <tr id="dong2">
        <td>Dòng 2 - ô 1 </td>
        <td>Dòng 2 - ô 2 </td>
        <td>Dòng 2 - ô 3 </td>
    </tr>
</table>
<h3>
    <button onclick="an()">Ẩn</button>
    <button onclick="hien()">Hien</button>
    <button onclick="chinhmaunen()">Chỉnh màu nền</button>
    <button onclick="chuhoa()">Cột cuối chữ hoa</button>
</h3>
<script>
function chuhoa(){
    tr_arr = document.getElementsByTagName("tr");
    for(var i=0; i<tr_arr.length ; i++){
        var str = tr_arr[i].children[2].innerText.toUpperCase();
        tr_arr[i].children[2].innerHTML = "<b>" + str +"</b>";
    }
}
function chinhmaunen(){
    mau = prompt("Nhập màu");
    obj = document.getElementById("tbl");
    obj.style.backgroundColor=mau;
}
function hien(){
    obj = document.getElementById("tbl");
    obj.style.display="";
}
function an(){
    obj = document.getElementById("tbl");
    obj.style.display="none";
}
function testchildren(){
    var obj =  document.getElementById("dong1");
    var socon = obj.children.length;
    console.log("Số con " + socon) ;
    var str = obj.children[1].innerHTML;
    console.log("Mã trong ô thứ 2 : " + str);
    var text = obj.children[1].innerText;
    console.log("Mã trong ô thứ 2 : " + text);
}
</script>
<script> testchildren();</script>

Ví dụ 2: thực tập chọn đối tượng theo class, theo tag, khóa nút, sửa nội dung

<style>
.cacsothich {
    width: 300px; margin: auto; border: solid 2px darkkhaki ; 
    padding: 0 20px; font-size: 1.1em; }
</style>
<div id="sothich">
    <h3>Sở thích của bạn là gì?</h3>
    <p> <span class="st"> Nhìn mua rơi</span> <em>13 </em> </p>
    <p> <span class="st"> Nghe chim hót</span> <em>15 </em> </p>
    <p> <span class="st"> Ngắm mây bay</span> <em>17 </em> </p>
    <p> <span class="st"> Uống trà</span> <em>20 </em> </p>
    <p> <span class="st"> Vuốt râu</span> <em> 25 </em> </p>
</div><hr>
<button onclick="xuly()">Xử lý</button>
<script>
function xuly(){
    var arr = document.getElementsByClassName("st");
    for(var i=0; i<arr.length ; i++){
        var sp = arr[i];       
        var em = sp.parentNode.getElementsByTagName("em")[0];
        var solan = em.innerText;
        em.innerText="";
        sp.innerText = sp.innerText.toUpperCase();
        sp.innerText = solan + ". " + sp.innerText;
    }
    document.getElementById("sothich").className="cacsothich";
    document.getElementsByTagName("button")[0].disabled=true;
}
</script>

Ví dụ 3; Thực tập lấy gúa trị của đối tượng hiện tại, chọn đối tượng trước, sau…

<head>
<style>
  #container { width: 500px; margin: auto;   }
  #container p { display: grid; padding: 10px 0;
        grid-template-columns: 200px 100px 70px auto;
        border-bottom: 1px solid lightcoral;        
    }
  #container p b:last-child { text-align: right;}
</style>
</head>
<body>
<div id="container">
<p> <span>Nói với tuổi 20</span>
    <b class="gia">56000</b><input value="10" onkeyup="tien(this)"><b class="tien">560000</b>
</p>
<p> <span>Mùi Hương Trầm</span>
    <b class="gia">120000</b><input value="10" onkeyup="tien(this)"><b class="tien">560000</b>
</p>
<p> <span>Hiểu về trái tim</span>
    <b class="gia">100000</b><input value="5" onkeyup="tien(this)"><b class="tien">500000</b>
</p>
</div>
</body>

<script>
function tien(obj){
    var soluong = obj.value;   
    var gia= ...; //lấy nội dung của đối tượng trước
    var tien=...; 
    //gán tiền vào dối  tượng sau

}
</script>

Mời bạn đọc các bài liên quan , bổ sung kiến thức:

https://longnv.name.vn/lap-trinh-javascript/vai-van-de-bo-sung-trong-javascript ,
https://longnv.name.vn/lap-trinh-javascript/lap-trinh-doi-tuong-trong-javascript-va-mo-hinh-bom