当前位置: 首页 > news >正文

Vue 3 TypeScript 接口(Interface)使用

在 Vue 3 中使用 TypeScript 时,接口(Interface)是定义类型的重要工具。接口可以帮助我们明确组件 props、数据模型、函数签名等内容的类型结构,提高代码可读性和可维护性。

接口在 Vue 3 中的常见应用场景

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) {// 现在可以安全访问props.user的属性const userName = computed(() => props.user.name);return { userName };}
});

2. 定义响应式数据模型

// 待办事项接口
interface TodoItem {id: number;title: string;completed: boolean;createdAt: Date;
}export default defineComponent({setup() {// 使用接口定义响应式数据const todos = ref<TodoItem[]>([{id: 1,title: '学习 Vue 3',completed: false,createdAt: new Date()}]);// 添加新待办事项的函数const addTodo = (title: string) => {const newTodo: TodoItem = {id: Date.now(),title,completed: false,createdAt: new Date()};todos.value.push(newTodo);};return { todos, addTodo };}
});

3. 定义复杂的状态对象

// 应用状态接口
interface AppState {isLoading: boolean;error: string | null;data: any[];page: number;
}export default defineComponent({setup() {// 使用接口定义状态对象const state = reactive<AppState>({isLoading: false,error: null,data: [],page: 1});// 获取数据的方法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 = '获取数据失败';} finally {state.isLoading = false;}};return { state, fetchData };}
});

4. 定义事件发射类型

// 自定义事件接口
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) => {// 类型安全的事件发射emit('update:name', newName);};const deleteItem = (id: number) => {// 类型安全的事件发射emit('delete', id);};return { updateName, deleteItem };}
});

5. 定义组合函数类型

// 计数器组合函数接口
interface Counter {count: Ref<number>;increment: () => void;decrement: () => void;reset: () => void;
}// 创建计数器的组合函数
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 响应类型

// API 响应接口
interface ApiResponse<T> {status: 'success' | 'error';message: string;data: T;timestamp: Date;
}// 用户数据接口
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. 接口继承

// 基础实体接口
interface BaseEntity {id: number;createdAt: Date;updatedAt: Date;
}// 用户接口继承基础实体
interface User extends BaseEntity {name: string;email: string;role: 'admin' | 'user';
}// 产品接口继承基础实体
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. 函数类型接口

// 比较函数接口
interface Comparator<T> {(a: T, b: T): number;
}// 在组件中使用
const sortUsers = (users: User[], comparator: Comparator<User>) => {return [...users].sort(comparator);
};// 创建比较器
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">文章数:</span><span class="stat-value">{{ stats.postCount }}</span></div><div class="stat-item"><span class="stat-label">关注者:</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;
}// 定义用户统计数据接口
interface UserStats {postCount: number;followerCount: number;followingCount: number;
}export default defineComponent({props: {user: {type: Object as PropType<User>,required: true}},setup(props, { emit }) {// 使用接口定义响应式状态const stats = reactive<UserStats>({postCount: 24,followerCount: 128,followingCount: 56});// 更新用户名的函数const updateName = () => {const newName = prompt('请输入新的用户名:');if (newName) {// 发射自定义事件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>

http://www.xdnf.cn/news/1118143.html

相关文章:

  • 【基于开源大模型(如deepseek)开发应用及其发展趋势的一点思考】
  • 西藏氆氇新生:牦牛绒混搭液态金属的先锋尝试
  • web:js的三种引用方式
  • MYSQL笔记1
  • 大模型之Langchain篇(二)——RAG
  • SQL的初步学习(二)(以MySQL为例)
  • 《区间dp》
  • Excalidraw:一款颠覆传统思维的免费开源绘图工具
  • DHS及HTTPS工作过程
  • JSON/AJAX/XHR/FetchAPI知识点学习整理
  • 代码随想录算法训练营第三十二天|动态规划理论基础、LeetCode 509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
  • std::sort的核心设计思想
  • 代码随想录算法训练营第十七天
  • MongoDB数据基本介绍
  • 从 Intel MacBook 迁移到 ARM MacBook 的完整指南
  • Windows怎样同步时间服务器?
  • 【网络实验】-BGP选路原则-11条
  • 攻防世界——Web题 very_easy_sql
  • 嵌入式 Linux开发环境构建之安装 SSH 软件
  • Spring AI 项目实战(十六):Spring Boot + AI + 通义万相图像生成工具全栈项目实战(附完整源码)
  • mapstruct与lombok冲突原因及解决方案
  • 2025年渗透测试面试题总结-2025年HW(护网面试) 44(题目+回答)
  • vue2入门(1)vue核心语法详解复习笔记
  • Agent篇
  • [Linux入门 ] RAID存储技术概述
  • 面向对象设计模式详解
  • 基于 STM32H743VIT6 的边缘 AI 实践:猫咪叫声分类 CNN 网络部署实战(已验证)中一些bug总结
  • OSPF 基础实验
  • 项目合作复盘:如何把项目经验转化为可复用资产
  • pthread_mutex_unlock函数的概念和用法