Thao tác với DOM trong JavaScript là gì?
Thao tác, tương tác với DOM hiểu ra cũng đơn giản như thế này:
"A, thằng áo đỏ kia. Bây giờ mày sẽ mặc áo xanh"
hoặc
"Thằng con con bên cạnh thằng áo đỏ kia, khi nghe tao ra hiệu mày sẽ chồng cây chuối"
Đó, Thao tác với DOM chỉ đơn giản là gọi đến thằng nào đó và bắt nó làm gì đó. :D
Với JavaScript, bạn có đầy đủ các công cụ để thao tác với các phần tử DOM. Nói chung, tất cả những gì mà HTML có, JavaScript đều có thể tác động, thay đổi được chúng:
-
JavaScript DOM có thể thay đổi các HTML elements
-
JavaScript DOM có thể thay đổi các HTML attributes
-
JavaScript DOM có thể thay đổi các CSS styles
-
JavaScript DOM có thể xóa bỏ (remove) các HTML elements và attributes
-
JavaScript DOM có thể thêm mới HTML elements và attributes
-
JavaScript DOM có thể tương tác với HTML events
-
JavaScript DOM có thể tạo các HTML events mới
Bên dưới đây mình sẽ giới thiệu một số thuộc tính thường sử dụng nhiều nhất trong DOM.
4.1. Thao tác với DOM sử dụng thuộc tính id
Thuộc tính id
sẽ trả vể ID của một phần tử là định danh duy nhất cho mỗi phần tử bạn có thể thay đổi ID nếu bạn muốn.
Để hiểu cách sử dụng thuộc tính id để thao tác với DOM thì hãy xem xét ví dụ sau:
Ví dụ thay đổi id message
thành xinChao
<body>
<p id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
<script>
var id = document.getElementsByTagName("p")[0].id = "xinChao";
//in ra id của p
document.write(document.getElementById("xinChao").id);
</script>
</body>
Trong mã HTML thì rõ ràng chúng ta đặt id
của thẻ p
là message
.
Nhưng khi chạy trên trình duyệt, bạn sẽ thấy thẻ <p>
có id
là xinChao
Câu lệnh này:
var id = document.getElementsByTagName("p")[0].id = "xinChao";
Viết liền như thế có thể sẽ làm bạn hơi khó hiểu.
Vì thế, mình sẽ viết lại như sau:
Đầu tiên,
// Lấy các phần tử p trong tài liệu
var arrays_p = document.getElementsByTagName("p");
Bây giờ chúng ta có arrays_p
là một tập hợp giống như một mảng, chứa các thẻ p
Và bạn còn nhớ cách truy cập mảng trong JavaScript rồi chứ?
> Nếu không thì đọc lại bài Mảng trong JavaScript này nhé.
Ở ví dụ trên mình đã cố tình để thẻ <p>
là phần tử ngay sau thẻ mở <body>
.
Thế nên, nó sẽ là phần tử đầu tiên trong mảng chúng ta lấy được.
Tiếp theo, ta sẽ gán id
mới cho phần tử này:
// Gán lại giá trị id cho phần tử p đầu tiên
arrays_p[0].id = "xinChao";
Cách làm này có vẻ là hơi rắc rối nhỉ.
Có cách nào làm khác không?
Có.
Phương thức document.getElementById()
cũng sẽ cho kết quả tương tự.
<p id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
<br />
<script>
var p = document.getElementById("message");
// Thay đổi id
p.id = "xinChao";
</script>
Thử chạy trên trình duyệt để xem kết quả bạn nhé.
Bây giờ, chúng ta đã nhắm đến chính xác phần tử p
có id
là message
để thực hiện thay đổi id thành công.
Vì sử dụng phương thức getElementById()
, bạn sẽ nhắm chính xác cho dù thẻ p này có nằm ở đâu đi nữa.
4.2. Thao tác với DOM sử dụng thuộc tính className
Sử dụng thuộc tính className
bạn có thể thực hiện gán class cho phần tử DOM nào đó.
Ví dụ, ta có file HTML như sau:
<html lang="en">
<head>
<title>DOM trong JavaScript</title>
<style>
.red {
color: red;
}
</style>
</head>
<body>
<p class="normal" id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
<button onclick="myFunction()">Nhấn vào để thành màu đỏ</button>
<script>
function myFunction() {
var x = document.getElementsByTagName("p")[0];
x.className = "red";
}
</script>
</body>
</html>
Sau khi click vào nút thì class normal
sẽ được thay thế bằng red
> Nếu bạn quên cách tạo hàm thì xin mời học lại bài Hàm trong JavaScript bạn nhé.
Nhưng lưu ý, cách làm này sẽ thay thế toàn bộ class trong phần tử p.
Để thêm được nhiều class thì đơn giản bạn chỉ cần tách các class bởi dấu cách như thế này: "red group1 smallTitel"
4.3. Thao tác với DOM sử dụng thuộc tính tagName
Thuộc tính tagName trả về tên của phần tử mà bạn nhắm tới.
Ví dụ:
<p id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
<script>
var tag_name = document.getElementById("message").tagName;
//in ra tên thẻ của p chính là p
document.write(tag_name);
</script>
4.4. Thao tác với DOM sử dụng thuộc tính innerHTML
Thuộc tính innerHTML (bên trong HTML) trả về mã HTML bên trong phần tử hiện tại.
Đoạn mã HTML này là chuỗi kí tự chứa tất cả phần tử bên trong, bao gồm các node phần tử và node văn bản.
Ví dụ:
<p id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
<p id="messages1"></p>
<script>
var value = document.getElementById("message").innerHTML;
document.getElementById("messages1").innerHTML = value;
</script>
Đoạn mã này đơn giản là lấy nội dung trong phần tử này và gán nó vào phần tử khác.
4.5. Thao tác với DOM sử dụng thuộc tính outerHTML
Trả về mã HTML của phần tử hiện tại. Có thể hiểu là outerHTML = tagName + innerHTML
Ví dụ, đây là tất cả mà outerHTML có thể lấy được.
<p id="message">Chào mừng các bạn đến với lập trình JavaScript căn bản!</p>
Ví dụ: Thay thế phần tử h1 thành h3
<h1 id="message">Xin chào các bạn đến với lập trình JavaScript căn bản!</h1>
<button onclick="myFunction()">Thay đổi Header</button>
<script>
function myFunction() {
document.getElementById("message").outerHTML =
"<h3 id='message_change'>Hello JS</h3>";
}
</script>
Như vậy, JavaScript sẽ tìm và thay thế toàn bộ h1 thành nội dung mà chúng ta gán cho nó.
Có nghĩa là sau khi bất vào nút Thay đổi Header
thì mã HTML sẽ trở thành như thế này:
<h3 id='message_change'>Hello JS</h3>
<button onclick="myFunction()">Thay đổi Header</button>
<script>
function myFunction() {
document.getElementById("message").outerHTML =
"<h3 id='message_change'>Hello JS</h3>";
}
</script>
4.6. Thao tác với DOM sử dụng thuộc tính attributes
Thuộc tính này sẽ trả về tập các thuộc tính của phần tử bạn nhắm đến mà nó nó như: id
, name
, type
, title
, href
, ….
Ví dụ: Đầu tiên ta có HTML như sau.
<!-- Ta có thuộc thẻ input có 4 thuộc tính type, id, onclick, value -->
<input type="button" id="btn" onclick="myFunction()" value="nhấn để xem" />
<p id="text"></p>
Bây giờ, ta có hàm như sau:
<script>
function myFunction() {
var x = document.getElementById("btn").attributes[3].name;
document.getElementById("text").innerHTML = x;
}
</script>
Cũng như mảng, thuộc tính này bắt đầu đếm từ 0
ở đây mình muốn xem tên thuộc tính thứ 4
thì sẽ gọi attributes[3]
như vậy kết quả trả về là value
4.7. Thao tác với DOM sử dụng thuộc tính style
Thuộc tính style được sử dụng để thiết lập CSS cho phần tử được nhắm đến.
Ví dụ:
<h1 id="myH1">Thay đổi màu của header</h1>
<button onclick="myFunction()">Nhấn nút này để chuyển sang màu đỏ</button>
<script>
function myFunction() {
// Thay đổi màu của thẻ H1
document.getElementById("myH1").style.color = "red";
}
</script>
Trong đó:
-
Tên thuộc tính CSS trong trường hợp này là color để điều chỉnh màu sắc của chữ.
Nếu tên thuộc tính có từ 2 từ trở lên: Ví dụ trong CSS bạn biết background-color
thì khi thiết lập style qua thuộc tính style này bạn sẽ cần viết là backgroundColor
Lưu ý: Từ từ đầu tiên viết thường, các từ tiếp theo viết HOA chữ cái đầu tiên, không có dấu gạch ngang như trong CSS.
Ví dụ.
Trong CSS ta viết như thế này:
background-color: gray;
Nhưng khi thiết lập qua DOM
với thuộc tính style
thì ta cần ghi như sau:
document.getElementById("myH1").style.backgroundColor = "red";
Ví dụ thiết lập viền cho phần tử (thuộc tính CSS có nhiều giá trị):
document.getElementById("myH1").style.border = "1px solid blue";
Khi thực hiện thành công, style
sẽ được thêm vào theo kiểu inline trên trình duyệt như thế này:
<h1 id="myH1" style = "border: 1px solid blue">Thay đổi màu của header</h1>
Đó, với DOM, bạn có thể thiết lập CSS cho phần tử mà không cần mở đến file CSS.
4.8. Một số thuộc tính quan hệ
Trong cây DOM, có rất nhiều các node có quan hệ với nhau như node cha, node anh chị em, node đầu tiên trong nhóm, node cuối cùng trong nhóm...
Tóm lại, các mối quan hệ như thế này đều có các thuộc tính tương ứng để cho phép bạn sử dụng.
-
parentNode
(node cha): Trỏ đến node cha của một node. Nếu một node không có node cha (document) thì parentNode
sẽ nhận giá trị là null
.
Ví dụ ta có HTML:
<ul id="khoaHoc">
<li>Học Java</li>
<li id="active">Học JavaScript</li>
<li>Học PHP</li>
<li>Học Pyton</li>
<li>NIIT - ICT Hà Nội</li>
</ul>
<div id="ketQua"></div>
Bây giờ, ta chọn đến node cha của thẻ li
có id là active
như thế này:
// Nhắm đến phần tử cha của phần tử id = active
let x = document.getElementById("active").parentNode;
console.log(x.nodeName); // Kết quả: UL
Đối với các thuộc tính quan hệ khác thì cũng tương tự.
-
childNodes
(các node con): Trỏ đến một đối tượng tương tự với mảng, chứa những node con của một node. Chỉ là tương tự với mảng thôi nha.
Ví dụ, trong trường hợp trên, ta lấy các phần tử li của thẻ ul
// Lấy các node con của phần tử ul
let y = document.getElementById("khoaHoc").childNodes;
// Kiểm tra xem lấy được bao nhiêu node
console.log(y.length); // Kết quả: 11
> Lưu ý: Trong DOM, tất cả các phần của tài liệu, chẳng hạn như phần tử, thuộc tính, văn bản, v.v đều tính là node
Do đó, tính cả các thẻ li
, id
, text
ở trong thẻ ul
trên ta có 11
node.
-
firstChild
(node con đầu tiên): Trỏ đến node con đầu tiên của một node trong childNodes
.
Ví dụ ta có HTML:
<ul id="khoaHoc"><li>A</li><li>B</li><li>C</li></ul>
<div id="ketQua"></div>
Lấy phần tử đầu tiên trong ul
// Lấy nội dung của thẻ li đầu tiên
var list = document.getElementById("khoaHoc").firstChild.innerHTML;
// Gán nội dung lấy được vào thẻ div
document.getElementById("ketQua").innerHTML = list;
> Lưu ý: Nếu có khoảng trống ở trước phần tử đầu tiên (dấu cách, xuống dòng, tab...) thì kết quả trả về là undefined
. Do đó bạn thấy mình phải đặt HTML như thế kia.
Vẫn còn rất nhiều các phần tử quan hệ như thế này. Bạn có thể đọc kỹ thêm tại đây.
Bên dưới đây mình có giải thích thêm một chút về một số node hay được sử dụng.
-
lastChild
(node con cuối cùng): Trỏ đến node con cuối cùng của một node trong childNodes
.
-
nextSibling
(node anh em liền kề sau): Trỏ đến node liền kề phía sau của nó (có cùng một parentNode).
-
previousSibling
(node anh em liền kề trước): Trỏ đến node liền kề phía trước (có cùng một parentNode).
Mỗi node trên cây DOM đều có 6 thuộc tính quan hệ để giúp bạn truy xuất gián tiếp theo vị trí của node :
-
Node.parentNode
: tham chiếu đến node cha của node hiện tại, và node cha này là duy nhất cho mỗi node. Do đó, nếu bạn cần tìm nguồn gốc sâu xa của 1 node, bạn phải nối thuộc tính nhiều lần, ví dụ Node.parentNode.parentNode
.
-
Node.childNodes
: tham chiếu đến các node con trực tiếp của node hiện tại, và kết quả là 1 mảng các đối tượng. Lưu ý rằng, các node con không bị phân biệt bởi loại node, nên kết quả mảng trả về có thể bao gồm nhiều loại node khác nhau.
-
Node.firstChild
: tham chiếu đến node con đầu tiên của node hiện tại, và tương đương với việc gọi Node.childNodes[0]
.
-
Node.lastChild
: tham chiếu đến node con cuối cùng của node hiện tại, tương đương với việc gọi Node.childNodes[Element.childNodes.length-1]
-
Node.nextSibling
: tham chiếu đến node anh em nằm liền kề sau với node hiện tại.
-
Node.previousSibling
: tham chiếu đến node anh em nằm liền kề trước với node hiện tại.
4.9. Một số phương thức phổ biến để thao tác với DOM khác
Như bạn đã biết, thông qua JavaScript chúng ta đã lấy được các phần tử HTML, thay đổi thuộc tính, thêm thuộc tính cho nó.
Ngoài ra bạn cũng có thể:
-
ceateElement(tagName)
: Tạo một node mới
-
createTextNode(text)
: Tạo một text Node mới
-
appendChild(node)
: Thêm một node con vào node hiện tại
Dưới đây là ví dụ thực hiện cho cả 3 phương thức trên.
HTML:
<ul id="khoaHoc">
<li>JavaScript</li>
<li>Java Full Stack</li>
<li>PHP Full Stack</li>
</ul>
<button onclick="themKhoaHoc()">Thêm Khóa học</button>
Bây giờ ta sẽ tạo một hàm để thêm một khóa học mới:
function themKhoaHoc() {
//Tạo thêm một đối tượng li
var node = document.createElement("li");
// Tạo một text node
var textnode = document.createTextNode("Full Stack DEV");
// Thêm text node vào node li vừa tạo
node.appendChild(textnode);
// Thêm phần tử vừa tạo vào cuối ul
document.getElementById("khoaHoc").appendChild(node);
}
Bạn thử chạy trên trình duyệt xem. Kết quả như thế nào?
Có thể thêm node thì cũng có thể xóa node với phương thức removeChild()
Đầu tiên, ta thêm một button nữa:
<button onclick="xoaKhoaHoc()">Xóa Khóa học</button>
Sau đó ta tạo một hàm xóa node đầu tiên trong ul:
function xoaKhoaHoc() {
// Chọn đến danh sách khóa học
let kh = document.getElementById("khoaHoc");
// Xóa phần tử con đầu tiên
kh.removeChild(kh.childNodes[0]);
}
Khi bấm vào nút Xóa khóa học
thì nó sẽ xóa thẻ li
đầu tiên trong ul
, và cứ thế.
Nhân tiện, tham khảo một số khóa học Lập trình tại NIIT - ICT Hà Nội để học lập trình web nhanh hơn:
-
KHÓA HỌC LẬP TRÌNH VIÊN (Full Stack - 12 tháng - Dành cho người muốn chuyển ngành hoặc học sinh mới tốt nghiệp THPT