TypeScript 集成

下面,我們來系統的梳理關于 Vue + TypeScript 深度集成 的基本知識點:


一、TypeScript 與 Vue 集成概述

1.1 為什么需要 TypeScript

  • 類型安全:編譯時類型檢查,減少運行時錯誤
  • 代碼智能:強大的IDE智能提示和自動補全
  • 可維護性:清晰的接口定義和類型約束
  • 團隊協作:統一的代碼規范和接口約定
  • 重構信心:安全地進行大規模代碼重構

1.2 Vue 與 TypeScript 集成方式

集成方式適用場景特點
選項式API傳統Vue項目遷移兼容性好,學習曲線平緩
組合式API新項目,復雜邏輯更好的類型推斷,更靈活
Class API面向對象背景開發者Vue 2主流方式,Vue 3可選
<script setup>現代Vue開發最簡潔的語法,最佳類型支持

二、基礎環境配置

2.1 創建支持 TypeScript 的 Vue 項目

使用 Vite 創建:
npm create vite@latest my-vue-ts-app -- --template vue-ts
使用 Vue CLI 創建:
vue create my-vue-ts-app
# 選擇 Manually select features → 勾選 TypeScript

2.2 關鍵配置文件

tsconfig.json
{"compilerOptions": {"target": "ESNext","module": "ESNext","strict": true,"jsx": "preserve","moduleResolution": "node","esModuleInterop": true,"skipLibCheck": true,"forceConsistentCasingInFileNames": true,"baseUrl": ".","paths": {"@/*": ["src/*"]},"types": ["vite/client"],"lib": ["ESNext", "DOM", "DOM.Iterable"]},"include": ["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"],"exclude": ["node_modules"]
}
vite.config.ts (Vite 項目)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { fileURLToPath, URL } from 'url'export default defineConfig({plugins: [vue()],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},server: {port: 8080}
})

三、組件開發模式

3.1 組合式API + <script setup>

<script setup lang="ts">
import { ref, computed } from 'vue'// Props 類型定義
interface Props {title: stringcount?: number
}const props = defineProps<Props>()// 事件聲明
const emit = defineEmits<{(e: 'update:count', value: number): void
}>()// 響應式數據
const message = ref<string>('Hello TS!')// 計算屬性
const reversedMessage = computed(() => {return message.value.split('').reverse().join('')
})// 方法
const increment = () => {emit('update:count', (props.count || 0) + 1)
}
</script><template><div><h1>{{ title }}</h1><p>{{ message }} → {{ reversedMessage }}</p><button @click="increment">Count: {{ count || 0 }}</button></div>
</template>

3.2 選項式API類型支持

<script lang="ts">
import { defineComponent } from 'vue'export default defineComponent({props: {title: {type: String,required: true},count: {type: Number,default: 0}},emits: ['update:count'],data() {return {message: 'Hello TS!' as string}},computed: {reversedMessage(): string {return this.message.split('').reverse().join('')}},methods: {increment(): void {this.$emit('update:count', this.count + 1)}}
})
</script>

四、類型系統增強

4.1 全局類型聲明

聲明全局屬性
// src/types/index.d.ts
import { Router } from 'vue-router'declare module '@vue/runtime-core' {interface ComponentCustomProperties {$router: Router$translate: (key: string) => string}
}
擴展全局組件類型
declare module '@vue/runtime-core' {export interface GlobalComponents {RouterLink: typeof import('vue-router')['RouterLink']RouterView: typeof import('vue-router')['RouterView']BaseButton: typeof import('./components/BaseButton.vue')['default']}
}

4.2 復雜類型工具

使用泛型約束 Props
import { PropType } from 'vue'interface User {id: numbername: stringemail: string
}export default defineComponent({props: {user: {type: Object as PropType<User>,required: true},permissions: {type: Array as PropType<('read' | 'write' | 'delete')[]>,default: () => ['read']}}
})
條件類型
type ButtonVariant = 'primary' | 'secondary' | 'text'
type ButtonSize = 'small' | 'medium' | 'large'interface ButtonProps {variant?: ButtonVariantsize?: ButtonSizedisabled?: boolean
}// 基于 Props 推導事件類型
type ButtonEmits = {click: [event: MouseEvent]hover: [isHovering: boolean]
}

五、狀態管理與類型安全

5.1 Pinia 狀態管理

類型化 Store
// stores/user.ts
import { defineStore } from 'pinia'interface User {id: numbername: stringemail: string
}interface UserState {currentUser: User | nullisAuthenticated: boolean
}export const useUserStore = defineStore('user', {state: (): UserState => ({currentUser: null,isAuthenticated: false}),actions: {async login(credentials: { email: string; password: string }) {const response = await api.login(credentials)this.currentUser = response.userthis.isAuthenticated = true},logout() {this.currentUser = nullthis.isAuthenticated = false}},getters: {username: (state) => state.currentUser?.name || 'Guest'}
})

5.2 Vuex 類型增強 (Vue 2)

import { createStore } from 'vuex'interface State {count: numberuser: User | null
}const store = createStore<State>({state: {count: 0,user: null},mutations: {setUser(state, payload: User) {state.user = payload},increment(state) {state.count++}},actions: {async fetchUser({ commit }, id: number) {const user = await api.getUser(id)commit('setUser', user)}},getters: {doubleCount: state => state.count * 2}
})

六、路由系統類型化

6.1 Vue Router 類型集成

import { createRouter, createWebHistory } from 'vue-router'// 定義路由元信息類型
declare module 'vue-router' {interface RouteMeta {requiresAuth?: booleantitle: string}
}const router = createRouter({history: createWebHistory(),routes: [{path: '/',component: () => import('@/views/Home.vue'),meta: { title: 'Home' }},{path: '/profile',component: () => import('@/views/Profile.vue'),meta: { requiresAuth: true,title: 'User Profile' }},{path: '/:pathMatch(.*)*',component: () => import('@/views/NotFound.vue'),meta: { title: 'Page Not Found' }}]
})// 導航守衛中使用類型
router.beforeEach((to, from) => {if (to.meta.requiresAuth && !isAuthenticated()) {return '/login'}
})

七、高級類型技巧

7.1 泛型組件

<script setup lang="ts" generic="T">
import { ref } from 'vue'defineProps<{items: T[]selected: T
}>()defineEmits<{(e: 'select', item: T): void
}>()
</script><template><ul><li v-for="item in items" :key="item.id"@click="$emit('select', item)">{{ item }}</li></ul>
</template>

7.2 類型安全的模板引用

<script setup lang="ts">
import { ref } from 'vue'const inputRef = ref<HTMLInputElement | null>(null)const focusInput = () => {inputRef.value?.focus()
}
</script><template><input ref="inputRef" type="text"><button @click="focusInput">Focus Input</button>
</template>

7.3 條件渲染類型收窄

interface User {id: numbername: string
}const user = ref<User | null>(null)// 使用類型守衛
function isUser(user: User | null): user is User {return user !== null
}// 在模板中使用
<template><div v-if="isUser(user)"><!-- 此處 user 類型為 User --><h1>{{ user.name }}</h1></div><div v-else>Loading...</div>
</template>

八、測試策略

8.1 組件單元測試

import { mount } from '@vue/test-utils'
import Counter from '@/components/Counter.vue'describe('Counter.vue', () => {it('emits increment event when clicked', async () => {const wrapper = mount(Counter, {props: {initialCount: 5}})await wrapper.find('button').trigger('click')expect(wrapper.emitted()).toHaveProperty('increment')expect(wrapper.find('button').text()).toContain('6')})
})

8.2 類型測試

// 使用 tsd 進行類型測試
import { expectType } from 'tsd'
import { useUserStore } from '@/stores/user'const store = useUserStore()// 測試 state 類型
expectType<number>(store.count)
expectType<User | null>(store.user)// 測試 getter 類型
expectType<string>(store.username)// 測試 action 類型
expectType<(credentials: { email: string; password: string }) => Promise<void>>(store.login)

九、性能優化

9.1 類型導入優化

// 使用類型導入減少運行時開銷
import type { Router } from 'vue-router'function useNavigation(router: Router) {// ...
}

9.2 避免 any 類型

// 使用 unknown 替代 any
function safeParse(data: string): unknown {return JSON.parse(data)
}// 使用類型守衛
function isUser(data: unknown): data is User {return typeof data === 'object' && data !== null && 'id' in data && 'name' in data
}// 使用類型斷言
const userData = safeParse(localStorage.getItem('user') || '{}') as User

十、實踐

10.1 項目結構組織

src/
├── assets/
├── components/
│   ├── ui/
│   └── business/
├── composables/         # 組合式函數
├── layouts/
├── router/
├── stores/
├── types/               # 全局類型聲明
│   ├── api.d.ts
│   ├── components.d.ts
│   └── index.d.ts
├── utils/               # 工具函數
├── views/
├── App.vue
└── main.ts

10.2 自定義 ESLint 規則

// .eslintrc.js
module.exports = {rules: {'@typescript-eslint/no-explicit-any': 'error','@typescript-eslint/explicit-function-return-type': ['error',{allowExpressions: true}],'vue/require-typed-props': 'error','vue/require-typed-emits': 'error'}
}

十一、常見問題解決

11.1 第三方庫類型缺失

# 安裝社區維護的類型聲明
npm install -D @types/lodash# 對于無類型聲明的庫
// src/shims.d.ts
declare module 'untyped-module' {const content: anyexport default content
}

11.2 模板事件處理類型

<script setup lang="ts">
const handleChange = (e: Event) => {// 類型收窄if (e.target instanceof HTMLInputElement) {console.log(e.target.value)}
}
</script><template><input type="text" @input="handleChange">
</template>

11.3 全局組件類型擴展

// src/types/components.d.ts
import type { DefineComponent } from 'vue'declare module 'vue' {export interface GlobalComponents {BaseButton: DefineComponent<{variant?: 'primary' | 'secondary'size?: 'small' | 'medium' | 'large'}>Icon: DefineComponent<{name: stringsize?: number}>}
}

十二、總結

Vue與TypeScript深度集成要點:

  1. 正確配置:搭建支持TS的Vue環境
  2. 組件開發:優先使用<script setup>語法
  3. 類型增強:擴展全局類型和組件類型
  4. 狀態管理:類型安全的Pinia/Vuex
  5. 路由系統:類型化的Vue Router配置
  6. 高級技巧:泛型組件、條件類型等
  7. 測試策略:單元測試與類型測試結合
  8. 性能優化:避免any,使用類型導入
基礎配置
組件開發
類型增強
狀態管理
路由系統
高級技巧
測試策略
性能優化
生產部署

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88117.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88117.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88117.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

npm proxy

背景 前端項目下載依賴時經常會出現timeout的情況&#xff0c;此時有三種解決方案。 切換鏡像源。 適用于對依賴版本要求不嚴格的情況。延長超時時間。設置npm proxy。一些生產環境對依賴版本有著嚴格要求&#xff0c;并且指定了依賴的下載地址&#xff08;如下圖&#xff09;&…

TVS管工作原理是什么?主要的應用場景都有哪些?

什么是TVS管&#xff1f; TVS&#xff08;Transient Voltage Suppressors&#xff09;&#xff0c;即瞬態電壓抑制器&#xff0c;也被稱為雪崩擊穿二極管&#xff0c;是一種二極管形式的高效能保護器件&#xff0c;常用來防止端口瞬間的電壓沖擊造成后級電路的損壞。 TVS 有單…

分布式微服務系統架構第156集:JavaPlus技術文檔平臺日更-Java線程池使用指南

title: java線程池使用 author: 哪吒 date: 2023-06-15點擊勘誤issues&#xff0c;哪吒感謝大家的閱讀Java線程池使用指南1. 線程池基礎使用1.1 創建線程池的方式方式一&#xff1a;使用Executors工具類&#xff08;不推薦&#xff09;// 1. 固定大小線程池 ExecutorService fi…

【最新版】點大全能版v2.6.7.1 含匯付斗拱插件+uniapp前端

一.介紹V2全能版本、獨立版本全開源&#xff0c;含鏈動21&#xff0c;匯付斗拱?、排隊免單、推三返1 &#xff0c;扶持金&#xff0c;平級獎&#xff0c;團隊業績獎&#xff0c;酒店管理&#xff0c;約車&#xff0c;餐飲等眾多營銷功能&#xff0c;商城系統版本號為2.6.7.1&a…

Go語言高級面試必考:切片(slice)你真的掌握了嗎?

目錄 1. 切片是個啥?從數組到切片的靈魂進化 數組與切片的愛恨情仇 切片的內存結構:三巨頭共舞 切片的初始化方式:靈活到飛起 切片的“引用”特性:福也是禍 源碼初探:切片的誕生 2. 切片三劍客:len、cap 和底層數組的三角戀 len 和 cap 的微妙關系 切片共享的秘密…

monorepo + Turborepo --- 開發應用程序

目錄 配置開發任務 在 dev 之前運行設置任務 運行特定應用程序 使用終端 UI 與任務交互 監聽模式 watch 將 turbo watch 與持久任務一起使用 依賴感知的持久任務 沒有依賴感知的持久任務 緩存 任務輸出 局限性 在 Monorepo 中開發應用程序可以解鎖強大的工作流程&…

C#字符串相關庫函數運用梳理總結 + 正則表達式詳解

C# 字符串常用庫函數總結 &#x1f539; 1. 字符串比較 方法說明示例string.Equals()比較兩個字符串是否相等&#xff08;可忽略大小寫&#xff09;string.Equals("abc", "ABC", StringComparison.OrdinalIgnoreCase) / !判斷兩個字符串是否相等/不等&quo…

投機采樣(Speculative Decoding)

投機采樣&#xff08;Speculative Decoding&#xff09; 是一種加速大型語言模型&#xff08;LLM&#xff09;推理的技術&#xff0c;其核心思想是通過預生成候選token序列并異步校驗&#xff0c;從而減少主模型的計算量&#xff0c;同時保持生成結果的準確性。 核心思想是通過…

如何將華為手機中的照片傳輸到電腦

華為手機在眾多手機品牌中以其出色的品質脫穎而出&#xff0c;尤其是其攝像頭功能。有時&#xff0c;你可能在華為手機上積累了太多有意義的照片&#xff0c;想要將這些照片上傳到電腦以釋放手機存儲空間。然而&#xff0c;出于用戶信息安全的考慮&#xff0c;一些便捷的方法可…

whitt算法之特征向量的尺度

whitt中特征值不相等判別條件另一個條件的意思&#xff0c; 實際上這兩個條件都沒用&#xff0c;不用看&#xff0c;特征值排序&#xff0c;如果現在順序對λ1/λ1‘ w λ2/λ2 -w 此時取相位就是0&#xff0c;最小了 如果相反就是面的是0我的代碼用最優相位內積去交換位置公…

【Note】《深入理解Linux內核》 第十九章:深入理解 Linux 進程通信機制

《深入理解Linux內核》 第十九章&#xff1a;深入理解 Linux 進程通信機制&#xff08;Process Communication&#xff09;關鍵詞&#xff1a;IPC、信號、管道、FIFO、消息隊列、信號量、共享內存、套接字、內核對象、同步機制一、進程通信概述 1.1 為什么需要進程通信 在 Linu…

【Mac 從 0 到 1 保姆級配置教程 19】- 英語學習篇-我的英語工作流分享(AI 輔助學習)

文章目錄前言聽力沉浸式翻譯閱讀Easydict配置自定義字典&#xff08;重點&#xff09;歐陸詞典沙拉查詞沉浸式翻譯寫作Eearthworm英文提問口語最后學習資料系列教程前言 本文介紹一下我日常如何學習和使用英語的工作流&#xff0c;包括一些常用好用的工具&#xff0c;好的工具…

從庫函數到API接口,深挖不同語言背后的“封裝”與“調用”思想

個人主頁-愛因斯晨 優秀文章推薦 文章目錄個人主頁-愛因斯晨優秀文章推薦引言一、三種調用機制概述C語言的庫函數Python 的導包機制Java 的 API 接口調用綜上&#xff1a;二、它們的相同點&#xff1a;封裝與調用三、不同之處**對比核心維度****細節串講**1. **C 語言&#xf…

基于NCNN框架在Android平臺實現YOLOv8目標檢測模型的高效部署與實踐

隨著移動設備計算能力的提升&#xff0c;越來越多的深度學習模型被部署到移動端&#xff0c;以實現實時、低延遲的應用場景。YOLO系列的在目標檢測任務中表現出色&#xff0c;具有精度高、速度快的優勢。本文將詳細介紹如何基于NCNN框架 &#xff0c;在Android平臺 上高效部署Y…

華為動態路由配置

問題描述&#xff1a;針對四個路由器在不同的網段場景中&#xff0c;對四個路由器進行動態路由配置。下面以如下場景為例&#xff0c;介紹詳細配置過程。配置過程&#xff1a; 1、每個路由器的接口配置IP地址 路由器AR1中每個接口配置IP地址。 sys # 進入系統視圖 interface g…

分布式事務解決方案(三)

在Java分布式系統領域&#xff0c;傳統強一致性方案&#xff08;如2PC、3PC&#xff09;在高并發、復雜業務場景下暴露出性能瓶頸和阻塞問題。而Saga模式與事件溯源&#xff08;Event Sourcing&#xff09;作為更具彈性和擴展性的解決方案&#xff0c;逐漸成為分布式事務處理和…

【時時三省】(C語言基礎)通過指針引用數組

山不在高&#xff0c;有仙則名。水不在深&#xff0c;有龍則靈。 ----CSDN 時時三省數組元素的指針一個變量有地址&#xff0c;一個數組包含若干元素&#xff0c;每個數組元素都在內存中占用存儲單元&#xff0c;它們都有相應的地址。指針變量既然可以指向變量&#xff0c;當然…

【WEB】Polar靶場 21-25題 詳細筆記

二十一.php very nicephp又是你 ,但是經過這么多次折磨后我感覺我已經有一點抗性了老規矩&#xff0c;先看知識點PHP 序列化是將 PHP 變量&#xff08;如對象、數組&#xff09;轉換為字符串的過程&#xff0c;便于存儲或傳輸。反序列化則是將字符串還原為原始變量。這在緩存、…

【Guava】1.0.設計虛擬機的方向

【Guava】1.0.設計虛擬機的方向虛擬機是什么&#xff1f;棧式虛擬機棧式虛擬機的優缺點題外話虛擬機是什么&#xff1f; 虛擬機&#xff08;VirtualMachine, VM&#xff09;是一種計算機程序或系統&#xff0c;它通過軟件模擬物理計算機的硬件運行環境&#xff0c;使得多個操作…

[附源碼+數據庫+畢業論文]基于Spring+MyBatis+MySQL+Maven+jsp實現的高校實驗室資源綜合管理系統,推薦!

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本高校實驗室資源綜合管理系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大…