跳至主要内容

84 篇文章 含有標籤「前端開發」

檢視所有標籤

HTML 入門教學筆記 | 學習筆記

· 閱讀時間約 4 分鐘
kdchang

1. 什麼是 HTML?

HTML(HyperText Markup Language,超文本標記語言)是建立網頁的標準語言。它用標籤(tags)來結構化內容,讓瀏覽器能夠解析並顯示網頁。HTML 主要負責網頁的結構,而樣式與行為則交由 CSS 和 JavaScript 負責。


2. HTML 文件基本結構

一個基本的 HTML 文件包含以下部分:

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一個 HTML 頁面</title>
</head>
<body>
<h1>歡迎來到我的網站</h1>
<p>這是一個簡單的 HTML 頁面。</p>
</body>
</html>
  • <!DOCTYPE html>:宣告 HTML5 文件類型。
  • <html lang="zh-TW">:定義 HTML 根標籤,lang="zh-TW" 表示使用繁體中文。
  • <head>:包含頁面的元資訊(meta information),如編碼、標題等。
  • <meta charset="UTF-8">:設定網頁使用 UTF-8 編碼,確保中文字元正確顯示。
  • <meta name="viewport" content="width=device-width, initial-scale=1.0">:讓網頁適應不同裝置的螢幕大小。
  • <title>:設定瀏覽器標籤上的標題。
  • <body>:放置網頁的主要內容,如標題、段落、圖片等。

3. 常見 HTML 標籤

3.1 標題與段落

HTML 提供六種標題 (<h1><h6>),以及 <p> 用來表示段落。

<h1>這是主標題</h1>
<h2>這是次標題</h2>
<h3>這是小標題</h3>
<p>這是一段文字,HTML 會自動換行。</p>
3.2 超連結

使用 <a> 標籤建立超連結:

<a href="https://www.google.com" target="_blank">前往 Google</a>
  • href 指定連結網址。
  • target="_blank" 讓連結在新視窗開啟。
3.3 圖片

使用 <img> 來插入圖片:

<img src="image.jpg" alt="示範圖片" width="300">
  • src 指定圖片來源。
  • alt 提供替代文字。
  • width 設定圖片寬度(可用 height 指定高度)。
3.4 清單

有序清單 (<ol>) 和無序清單 (<ul>):

<h2>購物清單</h2>
<ul>
<li>蘋果</li>
<li>香蕉</li>
<li>橘子</li>
</ul>

<h2>步驟</h2>
<ol>
<li>打開電腦</li>
<li>開啟瀏覽器</li>
<li>輸入網址</li>
</ol>
3.5 表格

使用 <table> 來建立表格,並搭配 <tr>(表格列)、<th>(表頭)、<td>(儲存格):

<table border="1">
<tr>
<th>姓名</th>
<th>年齡</th>
</tr>
<tr>
<td>小明</td>
<td>25</td>
</tr>
<tr>
<td>小華</td>
<td>30</td>
</tr>
</table>
  • border="1" 設定表格邊框。
3.6 表單

使用 <form> 來建立表單:

<form action="submit.php" method="post">
<label for="name">姓名:</label>
<input type="text" id="name" name="name" required>
<br>
<label for="email">電子郵件:</label>
<input type="email" id="email" name="email" required>
<br>
<input type="submit" value="提交">
</form>
  • action="submit.php" 指定表單提交到 submit.php
  • method="post" 指定使用 POST 方法傳遞數據。
  • required 讓輸入欄位變成必填。

4. HTML5 新增標籤

HTML5 引入了一些語義化標籤,使網頁更具結構性。

<header>
<h1>網站標題</h1>
</header>
<nav>
<ul>
<li><a href="#">首頁</a></li>
<li><a href="#">關於我們</a></li>
<li><a href="#">聯絡我們</a></li>
</ul>
</nav>
<section>
<h2>最新消息</h2>
<p>這是一則最新消息的內容。</p>
</section>
<footer>
<p>版權所有 &copy; 2025</p>
</footer>
  • <header>:頁首。
  • <nav>:導覽區塊。
  • <section>:內容區塊。
  • <footer>:頁尾資訊。

5. HTML 與 CSS 結合

雖然 HTML 定義了結構,但我們通常使用 CSS 來美化頁面。內嵌 CSS 可以寫在 <style> 內:

<style>
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
text-align: center;
}
h1 {
color: #007bff;
}
p {
font-size: 18px;
}
</style>

或者外部引入 CSS 檔案:

<link rel="stylesheet" href="styles.css">

6. 總結

這篇教學筆記介紹了 HTML 的基本語法,包括標籤、結構與常見元素。學會這些後,可以進一步學習 CSS 來美化網頁,或是學習 JavaScript 增強互動性。最好的學習方式是透過實際練習與製作小專案來熟悉 HTML 語法。

Vue.js 3 官方入門語法教學筆記 [13] - Slots 插槽 | 學習筆記

· 閱讀時間約 1 分鐘
kdchang

除了透過 Props 傳遞資料外,父元件還可以透過插槽將模板片段傳遞給子元件:

<template>
<ChildComp>
這是一些插槽內容!
</ChildComp>
</template>

在子元件中,可以使用 <slot> 元素作為插槽來渲染父元件傳遞的內容:

<template>
<!-- 子元件的模板 -->
<slot />
</template>

插槽內的內容會被視為「預設內容」:當父元件沒有傳遞插槽內容時,會顯示這些預設內容:

<template>
<slot>預設內容</slot>
</template>

目前我們尚未向 <ChildComp> 傳遞任何插槽內容,因此你應該會看到預設內容。現在試著利用父元件的 msg 狀態,為子元件提供一些插槽內容吧!

<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const msg = ref('from parent')
</script>

<template>
<ChildComp>Message: {{ msg }}</ChildComp>
</template>
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const msg = ref('from parent')
</script>

<template>
<ChildComp>Message: {{ msg }}</ChildComp>
</template>

Vue.js 3 官方入門語法教學筆記 [12] - Emits 事件傳遞 | 學習筆記

· 閱讀時間約 1 分鐘
kdchang

除了接收 Props 之外,子元件也可以向父元件觸發事件:

<script setup>
// 宣告要觸發的事件
const emit = defineEmits(['response'])

// 觸發事件並傳遞參數
emit('response', 'hello from child')
</script>

emit() 的第一個參數是事件名稱,任何額外的參數都會傳遞給事件監聽器。

父元件可以使用 v-on 來監聽子元件觸發的事件——如下範例中,處理函式接收來自子元件 emit 的額外參數,並將其賦值給本地狀態:

<template>
<ChildComp @response="(msg) => childMsg = msg" />
</template>

現在我們在編輯器中試試看吧!

Vue.js 3 官方入門語法教學筆記 [11] - Props 屬性 | 學習筆記

· 閱讀時間約 1 分鐘
kdchang

子元件可以透過 Props 接收來自父元件的輸入。首先,子元件需要宣告它所接收的 Props:

<!-- ChildComp.vue -->
<script setup>
const props = defineProps({
msg: String
})
</script>

注意,defineProps() 是一個編譯時的巨集,不需要額外匯入。一旦宣告後,msg Prop 就可以在子元件的模板中使用,也可以透過 defineProps() 返回的物件在 JavaScript 中存取。

父元件可以像設定屬性一樣,將 Prop 傳遞給子元件。若要傳遞動態值,也可以使用 v-bind 語法:

<template>
<ChildComp :msg="greeting" />
</template>

我們現在在編輯器中試試看吧!

<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const greeting = ref('Hello from parent')
</script>

<template>
<ChildComp :msg="greeting" />
</template>
<script setup>
const props = defineProps({
msg: String
})
</script>

<template>
<h2>{{ msg || 'No props passed yet' }}</h2>
</template>

Vue.js 3 官方入門語法教學筆記 [10] - Components 元件 | 學習筆記

· 閱讀時間約 1 分鐘
kdchang

到目前為止,我們只使用了一個單一的元件。實際的 Vue 應用程式通常是由巢狀元件所組成的。

父元件可以在其模板中渲染另一個元件作為子元件。要使用子元件,我們需要先匯入它:

import ChildComp from './ChildComp.vue'

然後,我們可以在模板中使用該元件,如下所示:

<template>
<ChildComp />
</template>

我們現在試試看將匯入子元件並將其渲染到模板中。

<script setup>
import ChildComp from './ChildComp.vue'
</script>

<template>
<ChildComp />
</template>
<template>
<h2>A Child Component!</h2>
</template>

Vue.js 3 官方入門語法教學筆記 [9] - Watchers 觀察者 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

有時我們可能需要以反應性的方式執行「Side-effect 副作用」,例如,當一個數值改變時將其記錄到控制台。我們可以使用觀察者來實現這一點:

import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newCount) => {
// 是的,console.log() 是一種副作用
console.log(`新的計數是:${newCount}`)
})

watch() 可以直接監視一個 ref,每當 count 的值改變時,回調函數就會被觸發。watch() 也可以監視其他類型的數據來源——更多細節請參閱指南:觀察者(Watchers)。

比將訊息記錄到控制台更實用的例子,可能是當一個 ID 發生變化時,根據新 ID 獲取數據。我們的代碼目前是在元件掛載時,從一個模擬 API 獲取 todos 數據。此外,還有一個按鈕可以遞增應該被獲取的 todo ID。請嘗試實現一個觀察者,在按下按鈕時根據新 ID 獲取新的 todo 數據。

參考範例:

<script setup>
import { ref, watch } from 'vue'

const todoId = ref(1)
const todoData = ref(null)

async function fetchData() {
todoData.value = null
const res = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
todoData.value = await res.json()
}

fetchData()

watch(todoId, fetchData)
</script>

<template>
<p>Todo id: {{ todoId }}</p>
<button @click="todoId++" :disabled="!todoData">Fetch next todo</button>
<p v-if="!todoData">Loading...</p>
<pre v-else>{{ todoData }}</pre>
</template>

Vue.js 3 官方入門語法教學筆記 [8] - Lifecycle and Template Refs 生命週期與模板引用 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

Lifecycle and Template Refs 生命週期與模板引用

到目前為止,Vue.js 透過響應式資料與聲明式渲染,幫助我們處理了所有的 DOM 更新。然而,無可避免地會有需要手動操作 DOM 的情況。

我們可以使用特殊的 ref 屬性來請求模板引用 (template ref),也就是模板中某個元素的引用:

範例

<template>
<p ref="pElementRef">hello</p>
</template>

定義引用

為了訪問這個引用,我們需要宣告一個名稱匹配的 ref

import { ref } from 'vue';

const pElementRef = ref(null);

請注意,這個 ref 在初始化時會是 null,因為當 <script setup> 被執行時,對應的 DOM 元素還不存在。模板引用只有在元件掛載 (mounted) 後才能被訪問。

在掛載後執行程式碼

我們可以使用 onMounted() 函式在掛載後執行程式碼:

import { onMounted } from 'vue';

onMounted(() => {
// 元件已掛載完成
});

生命週期鉤子

這稱為生命週期鉤子 (lifecycle hook),它允許我們在元件生命週期的特定時間點註冊回呼函式。其他的生命週期鉤子還包括 onUpdatedonUnmounted 等。更多細節請參考官方文件 生命週期圖示

試試看

現在,我們可以嘗試添加一個 onMounted 鉤子,透過 pElementRef.value 訪問 <p> 元素,並對其進行一些直接的 DOM 操作(例如更改 textContent)。

<script setup>
import { ref, onMounted } from 'vue'

const pElementRef = ref(null)

onMounted(() => {
pElementRef.value.textContent = 'mounted!'
})
</script>

<template>
<p ref="pElementRef">Hello</p>
</template>

Vue.js 3 官方入門語法教學筆記 [7] - Computed Property 計算屬性 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

讓我們在前一個待辦清單的範例基礎上繼續改進。這裡,我們已經為每個待辦項目新增了切換功能 (toggle),這是透過在每個待辦物件中新增一個 done 屬性,並使用 v-model 綁定到核取方塊來實現的:

<template>
<li v-for="todo in todos">
<input type="checkbox" v-model="todo.done">
...
</li>
</template>

接下來我們可以進一步改進功能,新增一個按鈕來隱藏已完成的待辦項目。我們已經有一個按鈕可以切換 hideCompleted 狀態。但要如何根據這個狀態來動態渲染不同的待辦清單項目呢?

這裡引入了 computed()。我們可以建立一個計算屬性,基於其他的響應式數據來源來計算它的 .value 值:

import { ref, computed } from 'vue';

const hideCompleted = ref(false);
const todos = ref([
/* ... */
]);

const filteredTodos = computed(() => {
// 根據 `todos.value` 和 `hideCompleted.value`
// 返回篩選後的待辦項目
});

我們將 v-for 的數據來源從原本的 todos 改為 filteredTodos

- <li v-for="todo in todos">
+ <li v-for="todo in filteredTodos">

計算屬性會自動追蹤其計算邏輯中使用的其他響應式數據作為依賴項目。它會快取計算結果,並在其依賴項目改變時自動更新。

現在,嘗試新增一個 filteredTodos 計算屬性,並實現其計算邏輯!如果實現正確,當隱藏已完成項目時,勾選一個待辦項目應會立即將其隱藏。

<script setup>
import { ref, computed } from 'vue'

let id = 0

const newTodo = ref('')
const hideCompleted = ref(false)
const todos = ref([
{ id: id++, text: 'Learn HTML', done: true },
{ id: id++, text: 'Learn JavaScript', done: true },
{ id: id++, text: 'Learn Vue', done: false }
])

const filteredTodos = computed(() => {
return hideCompleted.value
? todos.value.filter((t) => !t.done)
: todos.value
})

function addTodo() {
todos.value.push({ id: id++, text: newTodo.value, done: false })
newTodo.value = ''
}

function removeTodo(todo) {
todos.value = todos.value.filter((t) => t !== todo)
}
</script>

<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo" required placeholder="new todo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in filteredTodos" :key="todo.id">
<input type="checkbox" v-model="todo.done">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
<button @click="hideCompleted = !hideCompleted">
{{ hideCompleted ? 'Show all' : 'Hide completed' }}
</button>
</template>

<style>
.done {
text-decoration: line-through;
}
</style>

Vue.js 3 官方入門語法教學筆記 [6] - List Rendering 表單綁定 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

List Rendering 列表渲染
我們可以使用 v-for 指令根據一個來源陣列來渲染元素列表:

<template>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
</template>

在這裡,todo 是一個局部變數,代表目前被迭代的陣列元素。它的作用域僅限於 v-for 元素內部,類似於函式的作用域。


請注意,我們為每個 todo 對象指定了一個唯一的 id,並將其綁定為每個 <li> 的特殊 key 屬性。key 允許 Vue 精準地移動每個 <li>,以匹配陣列中對應對象的位置。


有兩種方式可以更新列表:

  1. 對來源陣列調用可變方法:

    todos.value.push(newTodo)
  2. 使用新的陣列替換:

    todos.value = todos.value.filter(/* ... */)

以下是一個簡單的待辦事項列表範例,您可以試著實現 addTodo()removeTodo() 方法,使其正常運作!

範例程式碼:

<template>
<div>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo.id)">Remove</button>
</li>
</ul>
<input v-model="newTodoText" placeholder="Add a new todo" />
<button @click="addTodo">Add Todo</button>
</div>
</template>

<script setup>
import { ref } from 'vue'

// 定義待辦事項列表和新增的文字
const todos = ref([
{ id: 1, text: 'Learn Vue.js' },
{ id: 2, text: 'Build a project' }
])

const newTodoText = ref('')

// 新增待辦事項
function addTodo() {
if (newTodoText.value.trim()) {
todos.value.push({
id: Date.now(), // 使用當前時間作為唯一 ID
text: newTodoText.value.trim()
})
newTodoText.value = '' // 清空輸入框
}
}

// 移除待辦事項
function removeTodo(id) {
todos.value = todos.value.filter(todo => todo.id !== id)
}
</script>

更多關於 v-for 的詳細內容,請參閱官方指南 - 列表渲染

<script setup>
import { ref } from 'vue'

// give each todo a unique id
let id = 0

const newTodo = ref('')
const todos = ref([
{ id: id++, text: 'Learn HTML' },
{ id: id++, text: 'Learn JavaScript' },
{ id: id++, text: 'Learn Vue' }
])

function addTodo() {
todos.value.push({ id: id++, text: newTodo.value })
newTodo.value = ''
}

function removeTodo(todo) {
todos.value = todos.value.filter((t) => t !== todo)
}
</script>

<template>
<form @submit.prevent="addTodo">
<input v-model="newTodo" required placeholder="new todo">
<button>Add Todo</button>
</form>
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo)">X</button>
</li>
</ul>
</template>

Vue.js 3 官方入門語法教學筆記 [5] - Conditional Rendering 表單綁定 | 學習筆記

· 閱讀時間約 2 分鐘
kdchang

Conditional Rendering 條件渲染
在 Vue 中,我們可以使用 v-if 指令來條件式渲染元素:

<template>
<h1 v-if="awesome">Vue is awesome!</h1>
</template>

這個 <h1> 只有在 awesome 的值為真值時才會被渲染。如果 awesome 的值變為假值,它將從 DOM 中被移除。


我們還可以使用 v-elsev-else-if 表示條件的其他分支:

<template>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
</template>

目前的範例同時顯示了兩個 <h1>,按鈕也沒有作用。請嘗試為 <h1> 添加 v-ifv-else 指令,並實作一個 toggle() 方法,使我們可以透過按鈕來切換顯示的內容。


示例程式碼範例:

<template>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
<button @click="toggle">Toggle</button>
</template>

<script setup>
import { ref } from 'vue'

const awesome = ref(true)

function toggle() {
awesome.value = !awesome.value
}
</script>

更多關於 v-if 的詳細內容請參閱官方指南 - 條件渲染

<script setup>
import { ref } from 'vue'

const awesome = ref(true)

function toggle() {
awesome.value = !awesome.value
}
</script>

<template>
<button @click="toggle">Toggle</button>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
</template>