一、Vue 組件基礎
在 Vue 中,組件是構建用戶界面的基本單位,它可以將頁面拆分成多個獨立、可復用的部分。一個 Vue 組件通常以 .vue 文件名結尾,包含三個核心部分:模板(Template)、腳本(Script)和樣式(Style)。
1.1 單文件組件(.vue 文件)結構
單文件組件(SFC)是 Vue 推薦的組件組織方式,其結構清晰,便于維護。
<template><!-- 模板部分:定義組件的 HTML 結構 --><div class="hello"><h1>{{ msg }}</h1></div></template><script setup><!-- 腳本部分:處理組件的邏輯 -->// 導入需要的模塊或組件import { ref } from 'vue'// 定義組件的數據const msg = ref('Hello Vue 3!')</script><style scoped>
<!-- 樣式部分:定義組件的樣式 -->.hello {color: blue;text-align: center;}</style>
- 模板(Template):必須包含在 <template> 標簽內,用于定義組件的渲染結構。一個組件的模板只能有一個根元素(Vue 3 支持多根元素,但通常建議使用一個根元素包裹)。
- 腳本(Script):使用 <script setup> 語法(Vue 3 推薦),用于編寫組件的邏輯,包括數據定義、方法聲明、生命周期鉤子等。setup 是 Vue 3 組合式 API 的入口點。
- 樣式(Style):包含在 <style> 標簽內,用于定義組件的樣式。添加 scoped 屬性后,樣式僅作用于當前組件,避免樣式污染。
1.2 組件的注冊與使用
組件分為全局注冊和局部注冊兩種方式,全局注冊的組件可在整個應用中使用,局部注冊的組件僅能在注冊它的父組件中使用。
1.2.1 全局注冊
在 main.js 中通過 app.component() 方法全局注冊組件:
// main.js
import { createApp } from 'vue'import App from './App.vue'import HelloWorld from './components/HelloWorld.vue'const app = createApp(App)// 全局注冊 HelloWorld 組件,第一個參數是組件名,第二個參數是組件對象app.component('HelloWorld', HelloWorld)app.mount('#app')
注冊后,可在任意組件的模板中直接使用:
<template><div><HelloWorld /></div>
</template>
1.2.2 局部注冊
在需要使用組件的父組件中,通過 import 導入組件后,在 components 選項中注冊:
<template><div><LocalComponent /></div></template><script setup>import LocalComponent from './components/LocalComponent.vue'// 在 setup 語法中,導入的組件會自動注冊,無需額外配置</script>
1.3 組件通信基礎(父傳子)
父組件通過 props 向子組件傳遞數據,子組件通過定義 props 接收數據。
父組件示例
<template><div><ChildComponent :message="parentMsg" :count="10" /></div></template><script setup>import { ref } from 'vue'import ChildComponent from './components/ChildComponent.vue'const parentMsg = ref('來自父組件的消息')</script>
子組件示例
<template>
<div>
<p>{{ message }}</p>
<p>接收的數字:{{ count }}</p>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
// 定義 props,指定接收的屬性名和類型
const props = defineProps({
message: String,
count: Number
})
// 使用 props 中的數據(直接通過 props.屬性名訪問)console.log(props.message)
</script>
在子組件中,defineProps 用于聲明接收的 props,可以指定屬性的類型、默認值、驗證規則等。父組件傳遞數據時,通過 v-bind(簡寫為 :)將數據綁定到子組件的屬性上。
二、模板語法
Vue 的模板語法是一種基于 HTML 的模板系統,它允許在 HTML 中嵌入 Vue 特有的語法,實現數據綁定、條件渲染、列表渲染等功能。
2.1 文本插值
使用雙大括號 {{ }} 可以將響應式數據插入到模板中,這稱為文本插值。
<template><div><p>基本文本:{{ username }}</p><p>表達式計算:{{ 1 + 2 * 3 }}</p><p>函數調用:{{ formatMessage('Hello') }}</p></div></template><script setup>import { ref } from 'vue'const username = ref('Vue 用戶')const formatMessage = (str) => {return str + ',歡迎使用 Vue 3'}</script>
雙大括號內可以是變量、表達式或函數調用,Vue 會自動計算并將結果渲染到頁面上。當數據發生變化時,插值內容會自動更新。
2.2 指令
指令是帶有 v- 前綴的特殊屬性,用于在模板中實現復雜的邏輯操作。
2.2.1 v-bind:綁定屬性
v-bind 用于動態綁定 HTML 屬性,可簡寫為 :。
<template>
<div>
<img v-bind:src="imageUrl" alt="圖片">
<a :href="linkUrl" :class="{ active: isActive }">鏈接</a>
</div>
</template>
<script setup>
import { ref } from 'vue'
const imageUrl = ref('https://vuejs.org/images/logo.png')
const linkUrl = ref('https://vuejs.org')
const isActive = ref(true)
</script>
<style>
.active {
color: red;
text-decoration: underline;
}
</style>
上述示例中,src、href、class 屬性的值通過 v-bind 綁定到響應式數據上,當數據變化時,屬性值會自動更新。class 還支持對象語法,根據 isActive 的值動態添加或移除 active 類。
2.2.2 v-on:事件綁定
v-on 用于綁定事件監聽器,可簡寫為 @。
<template>
<div>
<button v-on:click="handleClick">點擊按鈕</button>
<button @dblclick="handleDoubleClick">雙擊按鈕</button>
<input @input="handleInput" placeholder="輸入內容">
</div>
</template>
<script setup>
import { ref } from 'vue'
const handleClick = () => {
console.log('按鈕被點擊了')
}
const handleDoubleClick = () => {
console.log('按鈕被雙擊了')
}
const handleInput = (e) => {
console.log('輸入的內容:', e.target.value)
}
</script>
v-on 可以綁定各種 DOM 事件,事件處理函數可以接收事件對象 e,通過 e.target 等屬性獲取事件相關信息。
2.2.3 v-model:雙向數據綁定
v-model 用于在表單元素(如輸入框、復選框等)和響應式數據之間建立雙向綁定,即數據變化時表單元素的值會更新,表單元素的值變化時數據也會同步更新。
<template>
<div>
<input v-model="username" placeholder="輸入用戶名">
<p>您輸入的用戶名:{{ username }}</p>
<textarea v-model="content" placeholder="輸入內容"></textarea>
<p>文本域內容:{{ content }}</p>
<label>
<input type="checkbox" v-model="isAgree"> 同意協議
</label>
<p>是否同意:{{ isAgree }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue'
const username = ref('')
const content = ref('')
const isAgree = ref(false)
</script>
v-model 會根據表單元素的類型自動選擇合適的綁定方式,例如文本輸入框綁定 value 屬性和 input 事件,復選框綁定 checked 屬性和 change 事件。
2.2.4 條件渲染(v-if /v-else/v-else-if)
v-if、v-else、v-else-if 用于根據條件動態渲染元素。
<template><div><p v-if="score >= 90">優秀</p><p v-else-if="score >= 60">及格</p><p v-else>不及格</p><button @click="score += 10">加分</button><button @click="score -= 10" :disabled="score < 10">減分</button><p>當前分數:{{ score }}</p></div></template><script setup>import { ref } from 'vue'const score = ref(70)</script>
v-if 會根據條件決定是否渲染元素,如果條件為 false,元素會被從 DOM 中移除;而 v-show 則是通過 display: none 控制元素的顯示與隱藏,元素始終存在于 DOM 中。通常,頻繁切換顯示狀態時使用 v-show 性能更好,條件很少改變時使用 v-if 更合適。
2.2.5 列表渲染(v-for)
v-for 用于基于數組或對象渲染列表,語法為 v-for="(item, index) in items",其中 item 是數組元素,index 是元素的索引(可選)。
<template><div><h3>數組渲染</h3><ul><li v-for="(fruit, index) in fruits" :key="index">{{ index + 1 }}. {{ fruit }}</li></ul><h3>對象渲染</h3><ul><li v-for="(value, key) in user" :key="key">{{ key }}: {{ value }}</li></ul></div></template><script setup>import { ref, reactive } from 'vue'const fruits = ref(['蘋果', '香蕉', '橙子'])const user = reactive({name: '張三',age: 25,gender: '男'})</script>
使用 v-for 時,必須為每個列表項指定 key 屬性,key 的值應該是唯一的(通常使用數據的唯一標識,如 ID),以便 Vue 能夠高效地跟蹤列表項的變化,優化渲染性能。
2.3 事件修飾符
事件修飾符用于處理事件的默認行為或事件冒泡等問題,通過 .修飾符 的形式添加到 v-on 指令后。
常用的事件修飾符:
- .stop:阻止事件冒泡
- .prevent:阻止事件的默認行為
- .once:事件只觸發一次
- .self:只有事件目標是當前元素時才觸發事件
<template><div @click="parentClick"><button @click.stop="childClick">點擊(阻止冒泡)</button><a href="https://vuejs.org" @click.prevent="handleLinkClick">Vue 官網(阻止跳轉)</a><button @click.once="onceClick">只點擊一次</button></div></template><script setup>const parentClick = () => {console.log('父元素點擊事件')}const childClick = () => {console.log('子元素點擊事件')}const handleLinkClick = () => {console.log('鏈接被點擊')}const onceClick = () => {console.log('只觸發一次')}</script>
在上述示例中:
- .stop 阻止了子元素的點擊事件冒泡到父元素,因此點擊按鈕時只會觸發 childClick,不會觸發 parentClick。
- .prevent 阻止了鏈接的默認跳轉行為,點擊鏈接時只會執行 handleLinkClick。
- .once 使按鈕的點擊事件只觸發一次。