Vue中選項(xiàng)式和組合式API的使用詳解
Vue 的組件可以按兩種不同的風(fēng)格書(shū)寫(xiě) :組合式 API和選項(xiàng)式 API 。
組合式 API (Composition API)
通過(guò)組合式 API,可以使用導(dǎo)入的 API 函數(shù)來(lái)描述組件邏輯。在單文件組件中,組合式 API 通常會(huì)與
<script setup>
import { ref, onMounted } from 'vue'
// 響應(yīng)式狀態(tài)
const count = ref(0)
// 用來(lái)修改狀態(tài)、觸發(fā)更新的函數(shù)
function increment() {
count.value++
}
// 生命周期鉤子
onMounted(() => {
console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
<button @click="increment">Count is: {{ count }}</button>
</template>選項(xiàng)式 API (Options API)
使用選項(xiàng)式 API,可以用包含多個(gè)選項(xiàng)的對(duì)象來(lái)描述組件的邏輯,例如 data、methods 和 mounted。選項(xiàng)所定義的屬性都會(huì)暴露在函數(shù)內(nèi)部的 this 上,它會(huì)指向當(dāng)前的組件實(shí)例。
<script>
export default {
name: '', //`name` 屬性標(biāo)識(shí)組件名稱
components: { //使用 `components` 選項(xiàng)注冊(cè)子組件
}
// data() 返回的屬性將會(huì)成為響應(yīng)式的狀態(tài)
// 并且暴露在 `this` 上
data() {
return {
// 所有響應(yīng)式數(shù)據(jù)在這里定義
count: 0
};
},
// methods 是一些用來(lái)更改狀態(tài)與觸發(fā)更新的函數(shù)
// 它們可以在模板中作為事件處理器綁定
methods: {
// 所有組件方法在這里定義
},
// 生命周期鉤子會(huì)在組件生命周期的各個(gè)不同階段被調(diào)用
created() { /* 實(shí)例創(chuàng)建后 */ },
mounted() { /* DOM掛載后 */ },
updated() { /* 數(shù)據(jù)更新后 */ },
destroyed() { /* 實(shí)例銷毀前 */ },
// 組件注冊(cè)
components: {
// 子組件注冊(cè)
}
}
<script>export default 的作用
export default 是 ES6 模塊系統(tǒng)的語(yǔ)法,用于導(dǎo)出模塊的默認(rèn)內(nèi)容。在 Vue 中,它用于導(dǎo)出一個(gè) Vue 組件配置對(duì)象
export default {
// 組件配置選項(xiàng)
}當(dāng)在另一個(gè)文件中使用 import 時(shí),導(dǎo)入的就是這個(gè)默認(rèn)導(dǎo)出的對(duì)象。
data
- 作用:定義組件的響應(yīng)式數(shù)據(jù)
- 必須是函數(shù):返回一個(gè)包含數(shù)據(jù)的對(duì)象
- 為什么是函數(shù):確保每個(gè)組件實(shí)例都有獨(dú)立的數(shù)據(jù)副本,避免數(shù)據(jù)共享問(wèn)題
data() {
return {
newUser: { name: '', email: '' }, // 創(chuàng)建新用戶時(shí)的表單數(shù)據(jù)
users: [], // 存儲(chǔ)從API獲取的用戶列表
editingUser: null // 當(dāng)前正在編輯的用戶
};
}created
- 生命周期鉤子:在組件實(shí)例創(chuàng)建完成后立即調(diào)用
- 執(zhí)行時(shí)機(jī):數(shù)據(jù)觀測(cè)已建立,但DOM還未掛載
- 常見(jiàn)用途:初始化數(shù)據(jù)、調(diào)用API
created() {
this.fetchUsers(); // 組件創(chuàng)建時(shí)自動(dòng)獲取用戶列表
}methods
- 作用:定義組件的方法
- 特點(diǎn):這些方法可以直接在模板中調(diào)用
methods: {
// 異步獲取用戶列表
async fetchUsers() {
try {
const response = await axios.get('https://api.example.com/users');
this.users = response.data; // 更新響應(yīng)式數(shù)據(jù)
} catch (error) {
console.error('獲取用戶列表失敗:', error);
}
}
}
兩種風(fēng)格對(duì)比
組合式 API 的核心思想是直接在函數(shù)作用域內(nèi)定義響應(yīng)式狀態(tài)變量,并將從多個(gè)函數(shù)中得到的狀態(tài)組合起來(lái)處理復(fù)雜問(wèn)題。這種形式更加自由,也需要對(duì) Vue 的響應(yīng)式系統(tǒng)有更深的理解才能高效使用。相應(yīng)的,它的靈活性也使得組織和重用邏輯的模式變得更加強(qiáng)大。
選項(xiàng)式 API 是在組合式 API 的基礎(chǔ)上實(shí)現(xiàn)的。選項(xiàng)式 API 以“組件實(shí)例”的概念為中心 (即上述例子中的 this),基于面向?qū)ο蟾拍顚?shí)現(xiàn)。同時(shí),它將響應(yīng)性相關(guān)的細(xì)節(jié)抽象出來(lái),并強(qiáng)制按照選項(xiàng)來(lái)組織代碼。
以下是官方給出的建議:
- 在學(xué)習(xí)的過(guò)程中,推薦采用更易于理解的風(fēng)格。大部分的核心概念在這兩種風(fēng)格之間都是通用的。熟悉了一種風(fēng)格以后,也能夠很快地理解另一種風(fēng)格。
- 在生產(chǎn)項(xiàng)目中:
- 當(dāng)不需要使用構(gòu)建工具,或者打算主要在低復(fù)雜度的場(chǎng)景中使用 Vue,例如漸進(jìn)增強(qiáng)的應(yīng)用場(chǎng)景,推薦采用選項(xiàng)式 API。
- 當(dāng)你打算用 Vue 構(gòu)建完整的單頁(yè)應(yīng)用,推薦采用組合式 API + 單文件組件。
在其他 Vue 組件中導(dǎo)入和使用export default定義的組件 有幾種方式
基本導(dǎo)入和使用
導(dǎo)入組件
<template>
<div>
<!-- 使用導(dǎo)入的組件 -->
<ArticleList />
</div>
</template>
// 選項(xiàng)式
<script>
// 導(dǎo)入組件
import ArticleList from '@/components/ArticleList.vue'
export default {
name: 'ParentComponent',
components: {
// 注冊(cè)導(dǎo)入的組件
ArticleList
}
}
</script>調(diào)用子組件的方法
方法一:使用 ref 引用
<template>
<div>
<button @click="refreshArticles">刷新文章</button>
<button @click="createNewArticle">創(chuàng)建文章</button>
<!-- 給組件添加 ref 屬性 -->
<ArticleList ref="articleListRef" />
</div>
</template>
<script>
import ArticleList from '@/components/ArticleList.vue'
export default {
name: 'ParentComponent',
components: {
ArticleList
},
methods: {
refreshArticles() {
// 調(diào)用子組件的 fetchArticles 方法
this.$refs.articleListRef.fetchArticles()
},
createNewArticle() {
// 調(diào)用子組件的 handleCreateArticle 方法
this.$refs.articleListRef.handleCreateArticle()
}
}
}
</script>方法二:通過(guò) props 傳遞回調(diào)函數(shù)
父組件:
<template>
<div>
<ArticleList
:onRefresh="handleRefresh"
:onCreate="handleCreate"
/>
</div>
</template>
<script>
import ArticleList from '@/components/ArticleList.vue'
export default {
components: {
ArticleList
},
methods: {
handleRefresh() {
console.log('父組件處理刷新邏輯')
},
handleCreate(articleData) {
console.log('父組件處理創(chuàng)建邏輯', articleData)
}
}
}
</script>子組件 (ArticleList.vue):
<script>
export default {
name: 'ArticleList',
props: {
onRefresh: Function,
onCreate: Function
},
methods: {
fetchArticles() {
// 原有的獲取文章邏輯
fetch('http://localhost:8000/posts')
.then(r => r.json())
.then(data => {
this.articles = data
// 如果有傳遞回調(diào)函數(shù),則調(diào)用
if (this.onRefresh) {
this.onRefresh(data)
}
})
},
handleCreateArticle() {
// 原有的創(chuàng)建邏輯...
// 如果有傳遞回調(diào)函數(shù),則調(diào)用
if (this.onCreate) {
this.onCreate(this.newArticle)
}
}
}
}
</script>完整的父子組件通信示例
父組件
<template>
<div class="parent">
<h1>博客管理</h1>
<div class="controls">
<button @click="triggerRefresh" :disabled="isLoading">
{{ isLoading ? '加載中...' : '刷新文章' }}
</button>
<button @click="showCreateForm = true">新建文章</button>
</div>
<!-- 使用子組件 -->
<ArticleList
ref="articleList"
:externalCreateData="createFormData"
@articles-loaded="onArticlesLoaded"
@article-created="onArticleCreated"
/>
<!-- 父組件的創(chuàng)建表單 -->
<div v-if="showCreateForm" class="modal">
<h3>創(chuàng)建新文章</h3>
<input v-model="createFormData.title" placeholder="標(biāo)題">
<textarea v-model="createFormData.content" placeholder="內(nèi)容"></textarea>
<button @click="submitCreateForm">提交</button>
<button @click="cancelCreate">取消</button>
</div>
</div>
</template>
<script>
import ArticleList from '@/components/ArticleList.vue'
export default {
name: 'BlogManagement',
components: {
ArticleList
},
data() {
return {
isLoading: false,
showCreateForm: false,
createFormData: {
title: '',
content: ''
}
}
},
methods: {
// 觸發(fā)子組件的刷新方法
triggerRefresh() {
this.isLoading = true
this.$refs.articleList.fetchArticles()
},
// 觸發(fā)子組件的創(chuàng)建方法
submitCreateForm() {
this.$refs.articleList.handleCreateArticle(this.createFormData)
this.showCreateForm = false
},
cancelCreate() {
this.showCreateForm = false
this.createFormData = { title: '', content: '' }
},
// 監(jiān)聽(tīng)子組件的事件
onArticlesLoaded(articles) {
this.isLoading = false
console.log('文章加載完成:', articles)
},
onArticleCreated(newArticle) {
console.log('新文章創(chuàng)建:', newArticle)
this.createFormData = { title: '', content: '' }
}
}
}
</script>子組件 (ArticleList.vue)
<template>
<div class="article-list">
<div v-if="articles.length === 0" class="empty">暫無(wú)文章</div>
<ArticleCard
v-for="article in articles"
:key="article.id"
:article="article"
/>
</div>
</template>
<script>
import ArticleCard from './ArticleCard.vue'
export default {
name: 'ArticleList',
components: {
ArticleCard
},
props: {
// 從父組件接收創(chuàng)建數(shù)據(jù)
externalCreateData: {
type: Object,
default: () => ({ title: '', content: '' })
}
},
data() {
return {
articles: [],
newArticle: {
title: '',
content: '',
author: '左越'
}
}
},
watch: {
// 監(jiān)聽(tīng)外部創(chuàng)建數(shù)據(jù)的變化
externalCreateData: {
handler(newData) {
if (newData.title || newData.content) {
this.newArticle = { ...newData, author: '左越' }
this.handleCreateArticle()
}
},
deep: true
}
},
created() {
this.fetchArticles()
},
methods: {
async fetchArticles() {
try {
const response = await fetch('http://localhost:8000/posts')
const data = await response.json()
this.articles = data
// 觸發(fā)事件通知父組件
this.$emit('articles-loaded', data)
} catch (err) {
console.log('error', err)
this.$emit('articles-loaded', [])
}
},
async handleCreateArticle(externalData = null) {
const articleData = externalData || this.newArticle
if (!articleData.title.trim() || !articleData.content.trim()) {
alert('請(qǐng)?zhí)顚?xiě)所有字段')
return
}
try {
const response = await fetch('http://localhost:8000/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(articleData)
})
const newArticle = await response.json()
this.articles.unshift(newArticle)
// 觸發(fā)事件通知父組件
this.$emit('article-created', newArticle)
// 重置表單
this.resetForm()
} catch (err) {
console.error('error: ', err)
}
},
resetForm() {
this.newArticle = {
title: '',
content: '',
author: '左越'
}
}
}
}
</script>關(guān)鍵點(diǎn)總結(jié):
- 導(dǎo)入組件:使用
import ComponentName from 'path/to/component' - 注冊(cè)組件:在
components選項(xiàng)中注冊(cè) - 使用 ref:通過(guò)
this.$refs.refName.methodName()調(diào)用子組件方法 - 事件通信:子組件使用
this.$emit('event-name', data),父組件使用@event-name="handler" - Props 傳遞:父組件通過(guò) props 向子組件傳遞數(shù)據(jù)和方法
選擇哪種方式取決于具體需求:
- 簡(jiǎn)單的調(diào)用使用
ref - 復(fù)雜的通信使用
props和events - 狀態(tài)管理考慮使用 Vuex(對(duì)于大型應(yīng)用)
這種結(jié)構(gòu)讓 Vue 能夠自動(dòng)處理數(shù)據(jù)與視圖的同步,大大簡(jiǎn)化了前端開(kāi)發(fā)的復(fù)雜度。
愿你我都能在各自的領(lǐng)域里不斷成長(zhǎng),勇敢追求夢(mèng)想,同時(shí)也保持對(duì)世界的好奇與善意!
到此這篇關(guān)于Vue中選項(xiàng)式和組合式API的學(xué)習(xí)的文章就介紹到這了,更多相關(guān)vue選項(xiàng)式和組合式API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中如何實(shí)現(xiàn)復(fù)制內(nèi)容到剪切板詳解
有些業(yè)務(wù)需求需要點(diǎn)擊按鈕復(fù)制鏈接,下面這篇文章主要給大家介紹了關(guān)于vue中如何實(shí)現(xiàn)復(fù)制內(nèi)容到剪切板的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
vue 修改 data 數(shù)據(jù)問(wèn)題并實(shí)時(shí)顯示操作
這篇文章主要介紹了vue 修改 data 數(shù)據(jù)問(wèn)題并實(shí)時(shí)顯示操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09
vue學(xué)習(xí)筆記之指令v-text && v-html && v-bind詳解
這篇文章主要介紹了vue學(xué)習(xí)筆記之指令v-text && v-html && v-bind詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
Element中Select選擇器的實(shí)現(xiàn)
本文主要介紹了Element中Select選擇器的實(shí)現(xiàn),文中根據(jù)實(shí)例編碼詳細(xì)介紹的十分詳盡,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Vue3?通過(guò)作用域插槽實(shí)現(xiàn)樹(shù)形菜單嵌套組件
這篇文章主要為大家介紹了Vue3?通過(guò)作用域插槽實(shí)現(xiàn)樹(shù)形菜單嵌套組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
基于Vue實(shí)現(xiàn)圖片在指定區(qū)域內(nèi)移動(dòng)的思路詳解
這篇文章主要介紹了基于Vue實(shí)現(xiàn)圖片在指定區(qū)域內(nèi)移動(dòng),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11
基于vue3與supabase系統(tǒng)認(rèn)證機(jī)制詳解
這篇文章主要介紹了基于vue3與supabase系統(tǒng)認(rèn)證機(jī)制,,系統(tǒng)使用基于 JWT (JSON Web Token) 的認(rèn)證方式,提供了安全可靠的用戶身份管理機(jī)制,需要的朋友可以參考下2025-04-04
Vue3 組合式函數(shù)Composable最佳實(shí)戰(zhàn)
這篇文章主要為大家介紹了Vue3 組合式函數(shù)Composable最佳實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
element-ui中el-row中設(shè)置:gutter間隔不生效問(wèn)題
這篇文章主要介紹了element-ui中el-row中設(shè)置:gutter間隔不生效問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

