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ù)模型
// 待辦事項(xiàng)接口
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()
}
]);
// 添加新待辦事項(xiàng)的函數(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ǔ)實(shí)體接口
interface BaseEntity {
id: number;
createdAt: Date;
updatedAt: Date;
}
// 用戶接口繼承基礎(chǔ)實(shí)體
interface User extends BaseEntity {
name: string;
email: string;
role: 'admin' | 'user';
}
// 產(chǎn)品接口繼承基礎(chǔ)實(shí)體
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)文章希望大家以后多多支持腳本之家!
- 詳解TypeScript中type與interface的區(qū)別
- typeScript?核心基礎(chǔ)之接口interface
- typescript中type和interface的區(qū)別有哪些
- Typescript中interface自動化生成API文檔詳解
- TypeScript中的interface與type實(shí)戰(zhàn)
- TypeScript中type和interface的區(qū)別及注意事項(xiàng)
- Typescript中 type 與 interface 的區(qū)別說明總結(jié)
- TypeScript接口interface的高級用法詳解
- 解讀Typescript中interface和type的用法及區(qū)別
- TypeScript中type與interface的使用和區(qū)別
相關(guān)文章
vue打包靜態(tài)資源后顯示空白及static文件路徑報錯的解決
這篇文章主要介紹了vue打包靜態(tài)資源后顯示空白及static文件路徑報錯的解決,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
vue組件從開發(fā)到發(fā)布的實(shí)現(xiàn)步驟
這篇文章主要介紹了vue組件從開發(fā)到發(fā)布的實(shí)現(xiàn)步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11
vue-cli開發(fā)時,關(guān)于ajax跨域的解決方法(推薦)
下面小編就為大家分享一篇vue-cli開發(fā)時,關(guān)于ajax跨域的解決方法(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02

