0%

008重新認識JS-Day03-筆記2

DOM節點的選取

DOM除了有「HTML元素節點」外,還有「文字節點」、「註解節點」…等等。
選取DOM的節點方法如下:
ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
---html文件---
<div id="content">內容一</div>
<p class="paragraph">內文一</p>

<h2 class="title_two>標題二</h2>
<h2 class="title_two>標題二</h2>

---DOM節點擷取---
document.getElementsById('content');
document.getTagName('DIV');
document.getByClassNamw('paragraph');

document.querySelector('.paragraph'); // 回傳第一個符合該className的節點
document.querySelector('#content');  // 回傳第一個符合該id的節點

document.querySelectorAll('.paragraph'); // 回傳符合該className的NodeList

DOM節點間的查找遍歷(Traversing)

DOM節點與節點之間,大致分成以下兩種:
父子關係: 該節點的上一層node是「父節點」,該節點的下一層節點是「子節點」。
兄弟關係: 有同一個「父節點」的節點,彼此之間就稱為「兄弟節點」。

另外,有以下幾種方法可以取得子節點、父節點、兄弟節點的方法:
Node.childNodes: 會回傳的NodeList,並用這個回傳的NodeList來遍歷每個子節點
Node.firstChild: 取得Node節點的第一個子節點
Node.lastNodes: 取得Node節點的最後一個子節點
Node.parentNode: 取得父元素,回傳值有可能是一個元素節點、根節點 或 DocumentFragment
Node.previousSibling: 取得同一層之間的「前一個」節點,若該節點已經是 第一個節點 時,回傳null
Node.nextSibling: 取得同一層之間的「下一個」節點,若該節點已經是 最後一個節點 時,回傳null

document.getElementsBy*** 與 document.querySelector/document.querySelectorAll 的差異

  1. document.getElementById 以及 document.querySelector 只會取得一個元素/節點,故不會有index和length屬性。
  2. document.getElementsBy***document.querySelector/document.querySelectorAll 分別會回傳
    「HTML Collection」與「NodeList」。
    HTML Collection: 只收集HTML元素節點。
    NodeList除了HTML節點,也會回傳文字節點 和 屬性節點等。

    document.querySelector/document.querySelectorAll 取得的NodeList是靜態的

    即透過document.querySelector/document.querySelectorAll取得的NodeList,不會動態地隨著網頁元素的增減,跟著一起變動。

ex:

1
2
3
4
5
6
7
8
9
10
11
12
13
---HTML文件---
<div id="outer">
<div id="inner">inner</div>
</div>

---JavaScript文件---
var outerDiv = document.getElementById('outer');
var allDiv = document.querSelectorAll('div);
console.log(allDiv.length); // 2,目前有兩個div標籤元素

outerDiv.innerHTML = ''; //把outerDiv的內容全部清掉

console.log(allDiv.length); // 2,還是保持2,並沒有隨著outerDiv把內部元素清空而變成1

DOM Node 的建立、刪除、修改與外觀

DOM 節點的新增

  1. document.createElement(tagName)
    ex:
    1
    let newDiv = document.createElement('div');
    經過document.createElement(tagName)新增的元素,我們還無法在網頁上看到它們,
    需要透過appendChild()inserBefore()replaceChild()等方法,將這些新元素加入指定的位置,
    才能在網頁上看到它們。

另外,我們也可以直接對這些新增元素新增屬性
ex:

1
2
newDiv.id = 'newDiv';  // 新增id屬性
newDiv.className = 'box'; // 新增className
  1. document.createTextNode()
    a. 用來建立文字節點
    b. 在新增的TextNode被加入某個節點前,是無法看不到它的
    ex:

    1
    2
    3
    let newDiv = document.createElement('div');
    let newTextNode = document.createTextNode('Hello World');
    newDiv.appendChild(newTextNode); // 將newTextNode塞入newDiv裡面
  2. document.createDocumentFragment()
    a. 它是一種沒有父層節點的「最小化文件」
    b. 如同標準文件一般的方式來保存「片段的文件結構」
    c. DocumentFragment不是真實的DOM結構,
    所以,DocumentFragment變動並不會影響目前網頁文件,也不會導致回流(reflow)或引起
    任何影響效能的狀況。
    故當要大量操作DOM的元素時,用DocumentFragment的效能會比直接操作DOM還要好。

  3. document.write()
    可用write()將某內容寫入網頁中,其內容可以不只是單純的字串,也可以是HTML的標籤。

ex:

1
document.write("<h1>hello world</h1>");

甚至要新增<script>標籤,並指定外部js資源也是可以。
ex:

1
document.write("<script type=\"text\javascript\" src=\"file.js\">" + "<\/script>");

write()裡面的內容,會完全覆蓋目前網頁的內容。

DOM節點的修改與刪除

書中介紹了一下幾種方法

  1. NODE.appendChild(childNode)
    此方法會將childNode插入父容器節點末端
  2. NODE.insertBefore(newNode, refNode)
    將newNode節點插在redNode前面
  3. NODE.replaceChild(newChildNode, oldChildNode)
    將oldChildNode換成指定的newChildNode
  4. NODE.removeChild(childNode)
    將指定的子節點childNode刪除

修改元素的style屬性

透過JS來修改元素的style屬性,就是屬於修改「行內樣式」的類型。
ex:

1
2
3
4
5
6
---HTML文件---
<div class="box"></div>

---JS文件---
let box = document.querySlector('.box');
box.style.color = 'red';

a. 以上這種寫法的優先權會高過很多其他的寫法(!important除外)。
b. 另外,很多css屬性名中有破折號-,故你用上面這種JS修改的寫法得改成”駝峰式”的寫法
ex:

1
2
3
4
box.style.font-size = '10px';  // 不允許!!!

要改成下面這種寫法
box.style.fontSize = '10px'; // OK!!!

修改元素的class屬性

透過className來操作網頁標籤內的class屬性
ex:

1
2
3
4
5
6
---html文件---
<article id="article" class="small-font">......</article>

---JS文件---
let article = document.querySelector('#article');
article.className = 'large-font';

用以上這種寫法的話,會有一種問題,就是不會保留原本的className。
所以,DOM api提供了classList屬性來取代className

classList是一個唯讀的屬性。
即我們無法透過這個屬性直接更改class的屬性。
但能透過classList.add()classList.remove()來修改它。

ex:

1
2
3
4
5
6
7
8
9
---html文件---
<article id="article" class="small-font">......</article>

---JS文件---
let article = document.querySelector('.small-font');
article.classList.remove('.small-font');
article.classList.add('.large-font');

=>最後會變成<article id="article" class="large-font">......</article>

利用JavaScript直接寫入CSS樣式

way1. 在<head>利用document.write寫入CSS
ex:

1
document.write('<link rel="stylesheet" href="xxx.css"/>');

way2. 利用document.createElement來新增link標籤
ex:

1
2
3
4
5
6
7
8
let head = document.querySelector('head');
let linkTag = document.createElement('link');

if(某個條件){
linkTag.rel = 'stylesheet;
linkTag.type = 'text\css;
linkTag.href = 'customMobile.css;
}

以上這種方法,可以在滿足某個條件下,才寫入特定的CSS樣式