JavaScript 與 jQuery

第 5 章    文件物件模型

∗ 文件物件模型 (Document object model, DOM)

▸ 說明瀏覽器該如何為一份 HTML 文件建立模型

▸ DOM 並非 HTML 文件的一部分,也不是 JavaScript 的一部分,而是由瀏覽器在記憶體所建立的資料

▸ 瀏覽器利用模型樹 (DOM tree) 結構來建立此模型 ,因為此模型是由物件所建構而成,因此稱為物件模型

(1) 模型樹

∗ 模型樹 (DOM tree) 是一個網頁的模型架構

▸ 當瀏覽器載入一份網頁,它會建立該網頁的模型,此模型稱為 DOM tree

▸ DOM tree 儲存在瀏覽器的記憶體中

▸ HTML 文件範例與其 DOM tree:

ch5.html: 
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/ch5.css">
</head>
<body>

<div id="page">
  <h1 id="header">清單</h1>
  <h2>買雜貨</h2>
  <ul>
    <li id="one" class="hot"><em>新鮮</em>無花果</li>
    <li id="two" class="hot">松子</li>
    <li id="three" class="hot">蜂蜜</li>
    <li id="four">香醋</li>
  </ul>
</div>

<script src="js/ch5.js"></script>
</body>
</html>
ch5

▸ DOM tree 包含 4 種節點

✶ 文件節點 (Document node):樹的最頂端,代表整個網頁,也稱為文件物件 (Document object)
✶ 元素節點 (Element node):說明 HTML 頁面的結構,由 HTML 標籤 (Tag) 構成,存取模型樹資料的方式為尋找某個元素,找到後,就可以存取該元素的屬性或文字
✶ 屬性節點 (Attribute node):HTML 元素的開始標籤裡所置放的屬性
✶ 文字節點 (Text node):HTML 元素開始與結束標籤之間的文字

(2) 在 DOM tree 裡存取資料

∗ 在 DOM tree 裡存取資料包含 2 步驟:

1. 選擇 HTML 元素

2. 存取該元素的資料

∗ 利用 jQuery 選擇 HTML 元素

→ 利用選擇器 (Selector),與 CSS 選擇器格式相同

$('someTag'):選擇某個標籤 (Tag) 的所有元素

$('#someId'):選擇具有某個 id 的元素 (在一個頁面中,someId 應該是唯一,若有多個,只會回覆第一個)

$('.someClass'):選擇具有某個類別 (Class) 的所有元素

▸ 其他選擇模式:

$('*'):選擇所有標籤
$('<selector1>, <selector2>'):選擇多種元素 (<selector1><selector2> 可以是任何一種模式)
$('<selector1> > <selector2>'):選擇子元素
$('<selector1> <selector2>'):選擇後裔元素
$('<someTag#someId>'):選擇具有某個 id 之某個標籤元素
$('<someTag.someId>'):選擇具有某個 class 之某個標籤元素

∗ 在 DOM 裡遊走 (Traversing the DOM)

▸ 從某個元素到另一個元素

✶ 父元素:.parent()
✶ 子元素:.children()
✶ 前一個兄弟元素:.prev()
✶ 下一個兄弟元素:.next()
✶ 第一個元素:.first()
✶ 最後一個元素:.last()

▸ 練習:

✶ 下載 assets5.zip, 解壓縮後將 ch5.css 置於 ch5/css/ 目錄中, 其餘影像均置於 ch5/img/ 目錄中
element.html (類似 ch5.html):
...
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="js/element.js"></script>
...
js/element.js:
$(document).ready(function() {

  alert($('#two').next().html());               // 蜂蜜
  alert($('ul').children().last().html());      // 香醋

});

∗ 利用 jQuery 修改元素

▸ 修改內容

✶ 利用 .html(...) 方法修改元素內容
✶ 練習:
nodeValue.html (類似 ch5.html):
...
<script src="js/nodeValue.js"></script>
...
js/nodeValue.js:
$(document).ready(function() {

  $('#two').html('杏仁');             // 松子 --> 杏仁
  $('#one').html('煙燻<u>鮭魚</u>');  // <em>新鮮</em>無花果  --> 煙燻<u>鮭魚</u>

});

▸ 修改元素

✶ 在 DOM tree 中產生新元素或刪除元素:
# after():往後附加元素
# before():往前附加元素
# append():往後附加子元素
# prepend():往前附加子元素
# remove():刪除元素
✶ 練習:
addButton.html (類似 ch5.html):
...
<script src="js/addButton.js"></script>
...
js/addButton.js:
$(document).ready(function() {

  var $btn = $('<button></button>');    //  Create a new jQuery object
  var $one = $('#one');
  
  $one.after($btn.text('1').clone());    // Add text and clone the element
  $one.before($btn.text('2').clone());
  $one.append($btn.text('3').clone());
  $one.prepend($btn.text('4').clone());
  $('#two').remove();    // Remove 松子 

});

▸ 修改 HTML 元素屬性

✶ HTML 元素的屬性 (Attribute) 是名稱與值的配對,例如:<input type="radio">, 其中 type<input> 元素的屬性
✶ 取得屬性值:.attr(<attrName>) , 例如:$('input').attr('type')
# 練習:
addClass.html (類似 element.html):
...
<script src="js/addButton.js"></script>
...
js/addClass.js
$(document).ready(function() {

  var $one = $('#one');
  var $four = $('#four');
  
  console.log($one.attr('class'));
  if (!$four.attr('class')) {
    $four.attr('class', 'cool');
  }

});
# 設定 CSS 類別也可使用 .addClass('cool')
✶ 新增或修改屬性值:.attr(<attrName>, <value>),如果屬性不存在就新增,否則就修改
# 練習:
changeIdClass.html (類似 element.html):
... 
<link rel="stylesheet" href="css/changeIdClass.css">
...
<script src="js/changeIdClass.js"></script>
...
css/changeIdClass.css:
#red {
  color: red;
}

.blue {
  color: blue;
} 
js/changeIdClass.js:
$(document).ready(function() {

  var $two = $('#two');
  
  $two.attr('id', 'red');
  $two.next().attr('class', 'blue');

});
✶ 刪除屬性:.removeAttr(<attrName>)

▸ 修改 DOM 物件特性

✶ DOM 物件有特性 (Property),可由使用者或程式動態改變, 例如:<input type="radio" checked>,其中 checked<input> 元素在 DOM tree 的特性 (類似特性:selected, readonly, disabled, ...)
✶ DOM 物件另有其他特性,例如:window.location, tagName, nodeName, nodeType, ...
✶ 取得特性值:.prop(<propName>),例如:
HTML:
<input type="radio" name="price" checked>
jQuery:
$(document).ready(function() {

  console.log($('input[name=price]').prop('checked'));    // true

});
# 也可使用 .is(':checked') 檢查
✶ 新增或修改特性值:.prop(<propName>, <value>),如果特性不存在就新增, 否則就修改,例如:
HTML:同上
jQuery:
$(document).ready(function() {

  var $price = $('input[name=price]');
  
  $price.prop('checked', false);
  console.log($price.prop('checked'));    // false

});
✶ 刪除特性:.removeProp(<propName>) (僅能刪除由 .prop() 所新增的特性)

* 練習:在以下頁面中

▸ 在清單之前及之後分別加入「肉桂」與「芝麻」兩個新項目,結果:圖 a

▸ 將所有項目都改為熱賣,結果:圖 b

▸ 將項目總數量顯示在「買雜貨」之後,結果:圖 c

addElements.html (與 element.html 類似)

..

<div id="page">
 <h1 id="header">清單</h1>
 <h2 id="grocery">買雜貨</h2>
 <ul id="shoppingList">
   <li><em>新鮮</em>無花果</li>
   <li>松子</li>
   <li>蜂蜜</li>
   <li>香醋</li>
 </ul>
</div>

...
<script src="js/addElements.js"></script>
...

addElements.js

$(document).ready(function() {

  var $item = $('<li></li>');
  var $shopping = $('ul#shoppingList');
  $shopping.prepend($item.text('肉桂').clone());
  $shopping.append($item.text('芝麻').clone());

  var $shoppingList = $('ul#shoppingList').children();
  $shoppingList.addClass('hot');
  $('#grocery').append(':', $shoppingList.length);

});

shoppingListA.png 圖a

shoppingListB.png 圖b

shoppingListC.png 圖c

* 作業 5

上一章       下一章