[FE102] 前端必備:JavaScript (上)


Posted by s103071049 on 2021-05-24

前言 : 寫程式關注的面向到底是甚麼 ?

  1. 介面 : 如何改變介面
  2. 事件 : 如何監聽事件並做出反應
  3. 資料 : 如何跟伺服器交換資料/如何將資料在瀏覽器中保存下來

結論 : 任何程式都是這三樣。

JavaScript 與瀏覽器的溝通

執行 JavaScript 的一百種方式

js 可以在哪裡執行 ? 答:node.js、瀏覽器

怎麼在瀏覽器上執行 js ?

可以在 html 放 <script> js 程式碼 </script>,script 標籤放在不同的位置,會有些許不同。實作中會傾向將 js 程式碼引入進 html,而非直接在 html 加一堆 js code。

./ 表示相對路徑,同一個資料夾底下的 index.js。

<!DOCTYPE html>
<html>
<head>
  <title>test</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="./style.css">
  <link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css"/>
  <script src="./index.js"></script>
</head>

<body>
</body>

</html>
alert("yo yo yo")

node.js 與瀏覽器跑 js 的差別 ?

JS 的語法是相同,但某些地方瀏覽器不支援,但 node.js 支援,反之亦同。(原因:因為兩個執行環境不同)。
RMK:瀏覽器的執行環境能做的事情相對較少,node.js 較自由。

DOM 是什麼?

Document Object Model:將 document 轉換成 object。 document 是指在 html 寫的那些東西。目的:讓 JS 可以改 html 的介面。

我們可以將 html 的標記轉換成階層關係。轉換後類似物件,例如 : 我可以取到 body 這個物件,我可以取到它底下所有東西。
dmo 階層關係

雖然改的是 JS,但瀏覽器會幫助我們改動畫面實際的東西。所以,dom 是 js 與 html 的橋樑,或者更進一步說 dom 是 js 與瀏覽器之間的橋樑,

結論: JavaScript 是如何操作畫面的?是透過一個叫做 DOM(Document Object Model)的東西。簡單來說就是瀏覽器把畫面上那些 HTML 元素都轉成物件,並且提供給你一個 API 來操作它們。

如何選到想要的元素:getElement

瀏覽器提供很多方法讓我們選元素,以下我們將一一介紹。
(RMK:這些 function 都是放在 document 內, document 是瀏覽器提供的特殊物件,它將很多 function 都在放上面。)

一、getElementsByTagName

TagName = 標籤名稱。

發現印出的東西是空的,空陣列。
0: div
HTMLCollection(0) 可以先將 HTMLCollection 想像成特殊形態的陣列
length: 0

(原因:程式是由上而下跑,所以瀏覽器解析也是由上而下一段一段解析,故script 放置的位置會影響執行結果,因此在下方的代碼中當它解析 script 時,它尚未跑到 div 這段,所以這個時候電腦根本不知道 body 內是甚麼。)

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">

  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="./style.css">
  <link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css"/>
  <script src="./index.js"></script>
</head>

<body>
  <div>
    hello world!
  </div>
</body>
</html>
const elements = document.getElementsByTagName('div')
console.log(elements)

這也是為甚麼實務上,大家習慣將 script 放在</body>上,因為當我在這裡時,我看的到上面所有的資訊。

HTMLCollection [div]
0: div
length: 1

<body>
  <div>
    hello world!
  </div>
  <script src="./index.js"></script>
</body>

HTMLCollection(2) [div, div]
0: div
1: div
length: 2

<body>
  <div>
    hello world!
  </div>
  <div>
    ha ha ha ~
  </div>
  <script src="./index.js"></script>
</body>

結論:可以藉由 getElementsByTagName 來抓到屬於這個 tag 的元素。

二、getElementsByClassName

HTMLCollection(2) [div.block, div.block]
0: div.block
1: div.block
length: 2

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">

  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="./style.css">
  <link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css"/>

</head>

<body>
  <div class='block'>
    hello world!
  </div>
  <div class='block'>
    ha ha ha ~
  </div>
  <script src="./index.js"></script>
</body>
</html>
const elements = document.getElementsByClassName('block')
console.log(elements)

結論:可以藉由 getElementsByClassName 來抓到指定 ClassName 的東西。

三、getElementById

注意:因為 ID 只會有一個,所以這邊的 Element 不用加 s

// 會直接印出這個元素
<div id="block">
    hello world!
</div>
<body>
  <div id='block'>
    hello world!
  </div>
  <div>
    ha ha ha ~
  </div>
  <script src="./index.js"></script>
</body>
const elements = document.getElementById('block')
console.log(elements)

四、querySelector

querySelector 後面接的是 css 的選擇器。只會回傳匹配到的第一個元素。

const elements = document.querySelector('#block')
const elements = document.querySelector('div')
const elements = document.querySelector('.block2')
const elements = document.querySelector('div a')
const elements = document.querySelector('div>a')
<body>
  <div id='block'>
    hello world!
  </div>
  <div class='block2'>
    ha ha ha ~
    <a>hello</a>
  </div>
  <script src="./index.js"></script>
</body>

儘管我有兩個 div 它也只會回傳第一個 div。所以如果想選到所有的 div 可以怎麼做 ? A:使用 querySelectorAll。

五、querySelectorAll

NodeList(2) [div#block, div.block2] 很像陣列,但不是陣列
0: div#block
1: div.block2
length: 2

const elements = document.querySelectorAll('div')

改變元素的 CSS

用 element.style 後面接你要改的東西就可以了。

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">

  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
  <div id='block'>
    hello world!
  </div>
  <script src="./index.js"></script>
</body>
</html>
const elements = document.querySelector('#block')
element.style.background = 'red'
element.style.padding = '20px'

. 後面不能接 dash。所以有兩種方式:
第一種:[""],用字串包起來。
第二種:駝峰式

element.style['padding-top'] = '20px'
element.style.paddingTop = '20px'

程式碼很亂,改六個 style 就寫六次

const element = document.querySelector('#block')
console.log(element)
element.style.background = 'red'
element.style.width = '100px'
element.style.margin = 'auto'
element.style.border = '10px solid green'
element.style.padding = '4px'
element.style['text-align'] = 'center'

實作上,為了好維運。會先寫一個 class,再將 element 加上 class name。就可將 style 寫到 class 內,而不用寫到程式碼內。

改變元素的 Class

改變 class 再讓 class 去負責處理不同的內容會是比較好的方法。

如何讓 js 動態把 class 加上去 ? A : element.classList.add('class名稱')

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">

  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    .active {
      background: red;
    }
  </style>
</head>

<body>
  <div id='block'>
    hello world!
  </div>
  <script src="./index.js"></script>
</body>
</html>
const element = document.querySelector('#block')
element.classList.add('active')

多個可以分次寫

const element = document.querySelector('#block')
element.classList.add('active')
element.classList.add('active2')

如何將 class name 移除 ? A:element.classList.remove('class 名稱')

<body>
  <div id='block' class='main'>
    hello world!
  </div>
  <script src="./index.js"></script>
</body>
const element = document.querySelector('#block')
element.classList.remove('main')

開變關,關變開 element.classList.toggle('class 名稱') => 本來沒有會新增上去,本來有會移除。舉例來說,按鈕按下去會怎樣 ? 本來沒有按下去按了之後會變樣子/本來是按下去的,點了會變回原本的樣子。

與監聽事件一起合用,可以先試著玩一下,手動增加每一行這個會發生甚麼事

element.classList.toggle('main')

改變內容:inner、outer 的 HTML 與 text

一、innerText 改變文字內容

印出標籤內文字,不會將標籤一起顯示出來。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    .active {
      background: red;
    }
  </style>
</head>

<body>
  <div id='block'>
    hello world!
    <a>yo yo~</a>
  </div>
  <script src="./index.js"></script>
</body>
</html>
const element = document.querySelector('#block > a')
console.log(element.innerText)

通常不太會對 block 改它的 inner-text 會直接抓 a 改
顯示:hello world! have a good day.

const element = document.querySelector('#block > a')
element.innerText ='have a good day.'
console.log(element.innerText)

二、innerHTML 把標籤中的東西拿出

顯示結果:
 hello world!
    <a>yo yo~</a>
const element = document.querySelector('#block')

console.log(element.innerHTML)

三、outerHTML 標籤以內的東西拿出

把自己也抓出來。

顯示結果:
<div id="block">
    hello world!
    <a>yo yo~</a>
  </div>
const element = document.querySelector('#block')

console.log(element.outerHTML)

所以當我改,我可以改所有東西。

const element = document.querySelector('#block a')
element.outerHTML ='<h1>hi</h1>'
console.log(element.outerHTML)

最常使用 innerText, innerHTML

插入與刪除元素:appendChild 與 removeChild

一、removeChild

要刪除元素,需要知道它的 parent 是誰。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
    .active {
      background: red;
    }
  </style>
</head>

<body>
  <div id='block'>
    hello world!
    <a>yo yo~</a>
  </div>
  <script src="./index.js"></script>
</body>
</html>
const element = document.querySelector('#block')
element.removeChild(document.querySelector('a'))

如果我選錯東西會怎麼辦 ? 我會選到開頭的 a 但它並不是那個 child => 它會無法 remove。

<body>
  <a>111</a>
  <div id='block'>
    hello world!
    <a>yo yo~</a>
  </div>
  <script src="./index.js"></script>
</body>

二、appendChild

新增 element

const element = document.querySelector('#block')
const item = document.createElement('div')
item.innerText="123"
element.appendChild(item)

新增文字

const element = document.querySelector('#block')
const item = document.createTextNode('angela')
element.appendChild(item)

如何拿到旁邊元素、上面的上面的元素、如何插入到最前面,都有其它的 api,google 4 你的好朋友~ 操作是類似,只是要查找有哪些資源可以使用。










Related Posts

什麼是 SSR, SSG, ISR, CSR ?

什麼是 SSR, SSG, ISR, CSR ?

[04] JavaScript 入門 - 強制轉型、Truthy & Falsy、條件式

[04] JavaScript 入門 - 強制轉型、Truthy & Falsy、條件式

AI輔導室|快速完成網格繪製

AI輔導室|快速完成網格繪製


Comments