[Medium] 📄 Vue Basic & API
1. Can you describe the core principles and advantages of the framework Vue?
請描述 Vue 框架的核心原理和優勢
核心原理
Vue 是一個漸進式的 JavaScript 框架,其核心原理包含以下幾個重要概念:
1. 虛擬 DOM(Virtual DOM)
使用虛擬 DOM 來提升效能。它只會更新有變化的 DOM 節點,而不是重新渲染整個 DOM Tree。透過 diff 演算法比較新舊虛擬 DOM 的差異,只針對差異部分進行實際 DOM 操作。
// 虛擬 DOM 概念示意
const vnode = {
tag: 'div',
props: { class: 'container' },
children: [
{ tag: 'h1', children: 'Hello' },
{ tag: 'p', children: 'World' },
],
};
2. 資料雙向綁定(Two-way Data Binding)
使用雙向資料綁定,當模型(Model)更改時,視圖(View)會自動更新,反之亦然。這讓開發者不需要手動操作 DOM,只需關注資料的變化。
<!-- Vue 3 推薦寫法:<script setup> -->
<template>
<input v-model="message" />
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue';
const message = ref('Hello Vue');
</script>
Options API 寫法
<template>
<input v-model="message" />
<p>{{ message }}</p>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue',
};
},
};
</script>
3. 組件化(Component-based)
將整個應用切分成一個個組件,意味著重用性提升,這對維護開發會更為省工。每個組件都有自己的狀態、樣式和邏輯,可以獨立開發和測試。
<!-- Button.vue - Vue 3 <script setup> -->
<template>
<button @click="handleClick">
<slot></slot>
</button>
</template>
<script setup>
const emit = defineEmits(['click']);
const handleClick = () => {
emit('click');
};
</script>
4. 生命週期(Lifecycle Hooks)
有自己的生命週期,當資料發生變化時,會觸發相應的生命週期鉤子,這樣就可以在特定的生命週期中,做出相應的操作。
<!-- Vue 3 <script setup> 寫法 -->
<script setup>
import { onMounted, onUpdated, onUnmounted } from 'vue';
onMounted(() => {
// 組件掛載後執行
console.log('Component mounted!');
});
onUpdated(() => {
// 資料更新後執行
console.log('Component updated!');
});
onUnmounted(() => {
// 組件卸載後執行
console.log('Component unmounted!');
});
</script>
5. 指令系統(Directives)
提供了一些常用的指令,例如 v-if、v-for、v-bind、v-model 等,可以讓開發者更快速地開發。
<template>
<!-- 條件渲染 -->
<div v-if="isVisible">顯示內容</div>
<!-- 列表渲染 -->
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
<!-- 屬性綁定 -->
<img :src="imageUrl" :alt="imageAlt" />
<!-- 雙向綁定 -->
<input v-model="username" />
</template>
6. 模板語法(Template Syntax)
使用 template 來撰寫 HTML,允許將資料透過插值的方式,直接渲染到 template 中。
<template>
<div>
<!-- 文字插值 -->
<p>{{ message }}</p>
<!-- 表達式 -->
<p>{{ count + 1 }}</p>
<!-- 方法呼叫 -->
<p>{{ formatDate(date) }}</p>
</div>
</template>
Vue 的獨有優勢(和 React 相比)
1. 學習曲線較低
對團隊成員彼此程度的掌控落差不會太大,同時在書寫風格上,由官方統一規定,避免過於自由奔放,同時對不同專案的維護也能更快上手。
<!-- Vue 的單檔案組件結構清晰 -->
<template>
<!-- HTML 模板 -->
</template>
<script>
// JavaScript 邏輯
</script>
<style>
/* CSS 樣式 */
</style>
2. 擁有自己的獨特指令語法
雖然這點可能見仁見智,但 Vue 的指令系統提供了更直觀的方式來處理常見的 UI 邏輯:
<!-- Vue 指令 -->
<div v-if="isLoggedIn">歡迎回來</div>
<button @click="handleClick">點擊</button>
<!-- React JSX -->
<div>{isLoggedIn && '歡迎回來'}</div>
<button onClick="{handleClick}">點擊</button>
3. 資料雙向綁定更容易實現
因為有自己的指令,所以開發者實現資料雙向綁定可以非常容易(v-model),而 React 雖然也能實作類似的功能,但沒有 Vue 來得直覺。
<!-- Vue 雙向綁定 -->
<input v-model="username" />
<!-- React 需要手動處理 -->
<input value={username} onChange={(e) => setUsername(e.target.value)} />
4. 模板和邏輯分離
React 的 JSX 仍為部分開發者所詬病,在部分開發情境下,將邏輯和 UI 進行分離會顯得更易閱讀與維護。
<!-- Vue:結構清晰 -->
<template>
<div class="user-card">
<h2>{{ user.name }}</h2>
<p>{{ user.email }}</p>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: 'John',
email: 'john@example.com',
},
};
},
};
</script>
5. 官方生態系統完整
Vue 官方提供了完整的解決方案(Vue Router、Vuex/Pinia、Vue CLI),不需要在眾多第三方套件中選擇。
2. Please explain the usage of v-model, v-bind and v-html
請解釋
v-model、v-bind和v-html的使用方式
v-model:資料雙向綁定
當改變資料的同時,隨即驅動改變 template 上渲染的內容,反之改變 template 的內容,也會更新資料。
<template>
<div>
<!-- 文字輸入框 -->
<input v-model="message" />
<p>輸入的內容:{{ message }}</p>
<!-- 核取方塊 -->
<input type="checkbox" v-model="checked" />
<p>是否勾選:{{ checked }}</p>
<!-- 選項列表 -->
<select v-model="selected">
<option value="A">選項 A</option>
<option value="B">選項 B</option>
</select>
<p>選擇的選項:{{ selected }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
checked: false,
selected: 'A',
};
},
};
</script>
v-model 的修飾符
<!-- .lazy:改為在 change 事件後更新 -->
<input v-model.lazy="msg" />
<!-- .number:自動轉為數字 -->
<input v-model.number="age" type="number" />
<!-- .trim:自動過濾首尾空白字元 -->
<input v-model.trim="msg" />
v-bind:動態綁定屬性
常見於綁定 class 或連結、圖片等。當透過 v-bind 綁定 class 後,可以透過資料變動,來決定該 class 樣式是否被綁定,同理 API 回傳的圖片路徑、連結網址,也能透過綁定的形式來維持動態更新。
<template>
<div>
<!-- 綁定 class(可以簡寫為 :class) -->
<div :class="{ active: isActive, 'text-danger': hasError }">動態 class</div>
<!-- 綁定 style -->
<div :style="{ color: textColor, fontSize: fontSize + 'px' }">動態樣式</div>
<!-- 綁定圖片路徑 -->
<img :src="imageUrl" :alt="imageAlt" />
<!-- 綁定連結 -->
<a :href="linkUrl">前往連結</a>
<!-- 綁定自訂屬性 -->
<div :data-id="userId" :data-name="userName"></div>
</div>
</template>
<script>
export default {
data() {
return {
isActive: true,
hasError: false,
textColor: 'red',
fontSize: 16,
imageUrl: 'https://example.com/image.jpg',
imageAlt: '圖片描述',
linkUrl: 'https://example.com',
userId: 123,
userName: 'John',
};
},
};
</script>
v-bind 的簡寫
<!-- 完整寫法 -->
<img v-bind:src="imageUrl" />
<!-- 簡寫 -->
<img :src="imageUrl" />
<!-- 綁定多個屬性 -->
<div v-bind="objectOfAttrs"></div>