Vue 3 TypeScript 接口Interface使用示例詳解
在 Vue 3 中使用 TypeScript 時,接口(Interface)是定義類型的重要工具。接口可以幫助我們明確組件 props、數(shù)據(jù)模型、函數(shù)簽名等內(nèi)容的類型結(jié)構(gòu),提高代碼可讀性和可維護(hù)性。
接口在 Vue 3 中的常見應(yīng)用場景
1. 定義組件 Props 類型
// 用戶信息接口 interface User { id: number; name: string; email: string; age?: number; // 可選屬性 } // 在組件中使用 export default defineComponent({ props: { // 使用接口定義props類型 user: { type: Object as () => User, // 類型斷言 required: true }, // 簡單類型 isActive: { type: Boolean, default: false } }, setup(props) { // 現(xiàn)在可以安全訪問props.user的屬性 const userName = computed(() => props.user.name); return { userName }; } });
2. 定義響應(yīng)式數(shù)據(jù)模型
// 待辦事項接口 interface TodoItem { id: number; title: string; completed: boolean; createdAt: Date; } export default defineComponent({ setup() { // 使用接口定義響應(yīng)式數(shù)據(jù) const todos = ref<TodoItem[]>([ { id: 1, title: '學(xué)習(xí) Vue 3', completed: false, createdAt: new Date() } ]); // 添加新待辦事項的函數(shù) const addTodo = (title: string) => { const newTodo: TodoItem = { id: Date.now(), title, completed: false, createdAt: new Date() }; todos.value.push(newTodo); }; return { todos, addTodo }; } });
3. 定義復(fù)雜的狀態(tài)對象
// 應(yīng)用狀態(tài)接口 interface AppState { isLoading: boolean; error: string | null; data: any[]; page: number; } export default defineComponent({ setup() { // 使用接口定義狀態(tài)對象 const state = reactive<AppState>({ isLoading: false, error: null, data: [], page: 1 }); // 獲取數(shù)據(jù)的方法 const fetchData = async () => { state.isLoading = true; state.error = null; try { const response = await fetch(`/api/data?page=${state.page}`); state.data = await response.json(); } catch (err) { state.error = '獲取數(shù)據(jù)失敗'; } finally { state.isLoading = false; } }; return { state, fetchData }; } });
4. 定義事件發(fā)射類型
// 自定義事件接口 interface CustomEvents { (e: 'update:name', value: string): void; (e: 'delete', id: number): void; } export default defineComponent({ emits: ['update:name', 'delete'] as unknown as CustomEvents, setup(props, { emit }) { const updateName = (newName: string) => { // 類型安全的事件發(fā)射 emit('update:name', newName); }; const deleteItem = (id: number) => { // 類型安全的事件發(fā)射 emit('delete', id); }; return { updateName, deleteItem }; } });
5. 定義組合函數(shù)類型
// 計數(shù)器組合函數(shù)接口 interface Counter { count: Ref<number>; increment: () => void; decrement: () => void; reset: () => void; } // 創(chuàng)建計數(shù)器的組合函數(shù) export function useCounter(initialValue = 0): Counter { const count = ref(initialValue); const increment = () => count.value++; const decrement = () => count.value--; const reset = () => count.value = initialValue; return { count, increment, decrement, reset }; }
6. 定義 API 響應(yīng)類型
// API 響應(yīng)接口 interface ApiResponse<T> { status: 'success' | 'error'; message: string; data: T; timestamp: Date; } // 用戶數(shù)據(jù)接口 interface UserData { id: number; name: string; email: string; } // 在組件中使用 export default defineComponent({ setup() { const userData = ref<UserData | null>(null); const fetchUser = async (id: number) => { const response = await fetch(`/api/users/${id}`); const result: ApiResponse<UserData> = await response.json(); if (result.status === 'success') { userData.value = result.data; } }; return { userData, fetchUser }; } });
接口高級用法
1. 接口繼承
// 基礎(chǔ)實體接口 interface BaseEntity { id: number; createdAt: Date; updatedAt: Date; } // 用戶接口繼承基礎(chǔ)實體 interface User extends BaseEntity { name: string; email: string; role: 'admin' | 'user'; } // 產(chǎn)品接口繼承基礎(chǔ)實體 interface Product extends BaseEntity { name: string; price: number; description: string; category: string; }
2. 索引簽名
// 字典接口 interface Dictionary<T> { [key: string]: T; } // 在組件中使用 const colors: Dictionary<string> = { primary: '#3498db', secondary: '#2ecc71', danger: '#e74c3c' }; const permissions: Dictionary<boolean> = { canEdit: true, canDelete: false, canCreate: true };
3. 函數(shù)類型接口
// 比較函數(shù)接口 interface Comparator<T> { (a: T, b: T): number; } // 在組件中使用 const sortUsers = (users: User[], comparator: Comparator<User>) => { return [...users].sort(comparator); }; // 創(chuàng)建比較器 const byName: Comparator<User> = (a, b) => a.name.localeCompare(b.name); const byDate: Comparator<User> = (a, b) => a.createdAt.getTime() - b.createdAt.getTime();
完整示例:使用接口的 Vue 3 組件
<template> <div class="user-profile"> <h2>{{ user.name }}</h2> <p>郵箱: {{ user.email }}</p> <p v-if="user.age">年齡: {{ user.age }}</p> <div class="stats"> <div class="stat-item"> <span class="stat-label">文章數(shù):</span> <span class="stat-value">{{ stats.postCount }}</span> </div> <div class="stat-item"> <span class="stat-label">關(guān)注者:</span> <span class="stat-value">{{ stats.followerCount }}</span> </div> </div> <button @click="updateName">更新用戶名</button> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue'; // 定義用戶接口 interface User { id: number; name: string; email: string; age?: number; } // 定義用戶統(tǒng)計數(shù)據(jù)接口 interface UserStats { postCount: number; followerCount: number; followingCount: number; } export default defineComponent({ props: { user: { type: Object as PropType<User>, required: true } }, setup(props, { emit }) { // 使用接口定義響應(yīng)式狀態(tài) const stats = reactive<UserStats>({ postCount: 24, followerCount: 128, followingCount: 56 }); // 更新用戶名的函數(shù) const updateName = () => { const newName = prompt('請輸入新的用戶名:'); if (newName) { // 發(fā)射自定義事件 emit('update:name', newName); } }; return { stats, updateName }; } }); </script> <style scoped> .user-profile { max-width: 400px; margin: 0 auto; padding: 20px; border: 1px solid #e1e1e1; border-radius: 8px; background-color: #fff; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } h2 { color: #2c3e50; margin-bottom: 10px; } p { color: #7f8c8d; margin: 5px 0; } .stats { display: flex; margin: 20px 0; border-top: 1px solid #eee; padding-top: 15px; } .stat-item { flex: 1; text-align: center; } .stat-label { display: block; color: #95a5a6; font-size: 0.9rem; } .stat-value { display: block; font-size: 1.5rem; font-weight: bold; color: #3498db; } button { background-color: #3498db; color: white; border: none; padding: 10px 15px; border-radius: 4px; cursor: pointer; font-size: 1rem; transition: background-color 0.3s; } button:hover { background-color: #2980b9; } </style>
到此這篇關(guān)于Vue 3 TypeScript 接口(Interface)使用的文章就介紹到這了,更多相關(guān)Vue TypeScript 接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue2(三)實現(xiàn)子菜單展開收縮,帶動畫效果實現(xiàn)方法
這篇文章主要介紹了vue實現(xiàn)收縮展開效果的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04vue.js獲取數(shù)據(jù)庫數(shù)據(jù)實例代碼
本篇文章主要介紹了vue.js獲取數(shù)據(jù)庫數(shù)據(jù)實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05Vue 3 自定義權(quán)限指令 v-action的作用
在實際的前端開發(fā)中,尤其是涉及到權(quán)限管理的系統(tǒng),我們經(jīng)常需要根據(jù)用戶的權(quán)限動態(tài)控制某些按鈕的顯示和隱藏,這篇文章主要介紹了Vue 3 自定義權(quán)限指令 v-action的相關(guān)知識,需要的朋友可以參考下2025-04-04vue單頁面打包文件大?首次加載慢?nginx帶你飛,從7.5M到1.3M蛻變過程(推薦)
這篇文章主要介紹了vue單頁面打包文件大?首次加載慢?nginx帶你飛,從7.5M到1.3M蛻變過程,需要的朋友可以參考下2018-01-01關(guān)于vue的element-ui web端引入高德地圖并獲取經(jīng)緯度
這篇文章主要介紹了關(guān)于vue的element-ui web端引入高德地圖并獲取經(jīng)緯度,高德地圖首先要去申請key和密鑰,文中提供了部分實現(xiàn)代碼和解決思路,感興趣的朋友可以學(xué)習(xí)一下2023-04-04vue中當(dāng)圖片地址無效的時候,顯示默認(rèn)圖片的方法
今天小編就為大家分享一篇vue中當(dāng)圖片地址無效的時候,顯示默認(rèn)圖片的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Electron+Vue3+Vite搭建桌面應(yīng)用的示例代碼
本文主要介紹了Electron+Vue3+Vite搭建桌面應(yīng)用的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07