Vue TypeScript 實戰:掌握靜態類型編程

来源:https://www.cnblogs.com/Amd794/p/18240626
-Advertisement-
Play Games

這篇文章介紹瞭如何在TypeScript環境下為Vue.js應用搭建項目結構,包括初始化配置、創建Vue組件、實現狀態管理利用Vuex、配置路由以及性能優化的方法,旨在提升開發效率與應用性能。 ...



title: Vue TypeScript 實戰:掌握靜態類型編程
date: 2024/6/10
updated: 2024/6/10

excerpt:
這篇文章介紹瞭如何在TypeScript環境下為Vue.js應用搭建項目結構,包括初始化配置、創建Vue組件、實現狀態管理利用Vuex、配置路由以及性能優化的方法,旨在提升開發效率與應用性能。

categories:

  • 前端開發

tags:

  • TypeScript
  • Vue.js
  • 組件
  • 狀態管理
  • Vuex
  • 路由
  • 優化

image

第一章:Vue與TypeScript簡介

Vue.js的發展歷程和核心特性

Vue.js 是一個用於構建用戶界面的漸進式JavaScript框架。以下是Vue.js的發展歷程及其核心特性的概述:

  • 發展歷程

    • 2010年:Vue.js 的前身是一個內部項目,用於幫助Google的開發者構建UI。
    • 2014年:尤雨溪(Evan You)將Vue.js作為開源項目發佈。
    • 2016年:Vue.js 1.0 正式發佈,引入了虛擬DOM和組件系統。
    • 2016年:Vue.js 2.0 發佈,帶來了更強大的性能和靈活性。
    • 2020年:Vue.js 3.0 發佈,引入了Composition API、性能優化等新特性。
  • 核心特性

    • 聲明式渲染:Vue.js 通過簡潔的模板語法,實現了數據的聲明式渲染。
    • 組件系統:Vue.js 提供了組件化的開發方式,使得代碼更加模塊化、可復用。
    • 響應式系統:Vue.js 的響應式系統確保當數據變化時,UI 也會相應更新。
    • 雙向數據綁定:通過v-model指令,實現視圖與數據之間的雙向綁定。
    • 虛擬DOM:Vue.js 使用虛擬DOM來提高渲染效率,減少不必要的DOM操作。
    • 路由和狀態管理:Vue.js 通過 Vue Router 和 Vuex 提供了路由和狀態管理的解決方案。

TypeScript的出現背景及其優勢

TypeScript 是 JavaScript 的一個超集,添加了靜態類型選項。以下是TypeScript的出現背景及其優勢的介紹:

  • 出現背景

    • 隨著JavaScript應用規模的擴大,開發者面臨著類型錯誤、代碼維護困難等問題。
    • 需要一種能夠在編寫代碼時提供類型檢查和代碼提示的語言,以提高開發效率和代碼質量。
  • 優勢

    • 類型安全:TypeScript 提供了靜態類型系統,有助於在編譯階段發現潛在的錯誤。
    • 更好的工具支持:TypeScript 支持先進的代碼編輯器特性,如智能提示、代碼重構、導航等。
    • 可維護性:類型定義提供了代碼的文檔化,使得代碼更易於理解和維護。
    • 向後相容:TypeScript 最終編譯為 JavaScript,可以在任何支持 JavaScript 的環境中運行。

Vue與TypeScript的結合帶來的好處

將 Vue.js 和 TypeScript 結合使用,可以帶來以下好處:

  • 類型檢查:TypeScript 的類型系統可以在開發階段幫助檢測錯誤,減少運行時的問題。
  • 組件類型定義:TypeScript 提供了對 Vue 組件屬性的強類型定義,增加了代碼的清晰度和可維護性。
  • 代碼重構:TypeScript 支持代碼重構,使得對大型 Vue 項目的修改更加安全和高效。
  • 開發效率:TypeScript 的智能提示和代碼補全功能可以加快開發速度,減少查找文檔的時間。
  • 更好的協作:TypeScript 的類型定義有助於團隊成員更好地理解和使用彼此的代碼。

第二章:環境搭建與項目初始化

安裝Node.js和npm

在開始使用Vue和TypeScript之前,需要安裝Node.js和npm(Node.js包管理器)。以下是安裝步驟:cmdragon's Blog

  1. 下載Node.js安裝包: 訪問 Node.js
    官方網站(https://nodejs.org/),根據操作系統下載適合的安裝包。

  2. 安裝Node.js

    • 在 Windows 上,運行下載的.msi安裝文件並遵循提示完成安裝。
    • 在 macOS 上,運行下載的.pkg安裝文件並遵循提示完成安裝。
    • 在 Linux 上,可以使用包管理器(如aptyum等)或從源代碼編譯。
  3. 驗證安裝: 打開命令行工具,輸入以下命令:

    node -v
    npm -v
    
    

    如果安裝成功,將顯示 Node.js 和 npm 的版本號。

使用Vue CLI創建項目

Vue CLI 是 Vue.js 的官方命令行工具,用於快速搭建Vue項目架構。以下是使用Vue CLI創建項目的步驟:

  1. 安裝Vue CLI: 在命令行中運行以下命令全局安裝Vue CLI:

    npm install -g @vue/cli
    
    
  2. 創建新項目: 使用以下命令創建一個新的Vue項目:

    vue create my-vue-project
    
    

    在創建過程中,CLI會詢問一些問題來幫助你選擇項目的配置。

  3. 進入項目: 創建完成後,進入項目文件夾:

    cd my-vue-project
    
    

集成TypeScript到Vue項目

如果在使用Vue CLI創建項目時沒有選擇TypeScript,可以手動將其集成到項目中:

  1. 安裝TypeScript: 在項目根目錄下運行以下命令:

    npm install typescript --save-dev
    
    
  2. 創建tsconfig.json: 在項目根目錄下創建一個tsconfig.json文件,這是TypeScript項目的配置文件。

  3. 修改Vue CLI配置: 根據項目配置,可能需要修改vue.config.js文件來啟用TypeScript支持。

配置TypeScript編譯選項

tsconfig.json文件包含TypeScript編譯器的選項。以下是一個基本的tsconfig.json配置示例:

{
  "compilerOptions": {
    "target": "esnext",        // 編譯到哪個ECMAScript版本
    "module": "esnext",         // 使用的模塊系統
    "strict": true,            // 啟用所有嚴格類型檢查選項
    "jsx": "preserve",         // 在.tsx文件中保留JSX
    "moduleResolution": "node",// 模塊解析策略
    "experimentalDecorators": true, // 啟用裝飾器
    "esModuleInterop": true,   // 允許預設導入非ES模塊
    "skipLibCheck": true,      // 跳過所有聲明文件(*.d.ts)的類型檢查
    "forceConsistentCasingInFileNames": true // 強制文件名大小寫一致性
  },
  "include": [
    "src/**/*.ts",             // 包含的文件
    "src/**/*.tsx",
    "src/**/*.vue"
  ],
  "exclude": [
    "node_modules",           // 排除的文件
    "**/*.spec.ts"
  ]
}

這個配置文件設置了TypeScript編譯器的基本選項,包括目標代碼版本、模塊系統、嚴格類型檢查等。根據項目需求,可以進一步調整這些選項。

第三章:TypeScript基本類型

TypeScript 是 JavaScript 的超集,添加了靜態類型系統。在 TypeScript 中,你可以為變數指定類型,這樣可以在編譯時期就捕捉到可能的錯誤。

基礎類型(string、number、boolean等)

TypeScript 支持多種基礎數據類型,以下是一些常用的基礎類型:

  • string:字元串類型,用來表示文本數據。
  • number:數字類型,包括整數和浮點數。
  • boolean:布爾類型,可以是true或者false
  • nullundefined:表示空值或未定義的值。
  • void:表示沒有返回值的函數。

示例代碼:

let name: string = "張三";
let age: number = 30;
let isStudent: boolean = true;
let notSure: any = 4;
let notDefined: undefined = undefined;
let nullValue: null = null;

聯合類型、交叉類型和類型別名

  • 聯合類型:表示一個變數可以是幾種不同類型之一。

    示例代碼:

    let value: string | number;
    value = "Hello";
    value = 100;
    
    
  • 交叉類型:表示一個變數是多個類型的組合。

    示例代碼:

    interface Person {
      name: string;
    }
    interface Student {
      age: number;
    }
    type PersonStudent = Person & Student;
    let personStudent: PersonStudent = { name: "張三", age: 20 };
    
    
  • 類型別名:可以為類型起一個新名字。

    示例代碼:

    type Length = number;
    let height: Length = 180;
    
    

any、unknown和never類型

  • any類型:用於表示一個變數可以是任何類型。使用 any 類型會關閉類型檢查。

    示例代碼:

    let anything: any;
    anything = "hello";
    anything = 1;
    anything = true;
    
    
  • unknown類型:表示未知類型的值,是類型安全的 any。對 unknown 類型的變數進行任何操作之前,必須進行類型檢查。

    示例代碼:

    let valueUnknown: unknown;
    valueUnknown = "hello";
    valueUnknown = 1;
    if (typeof valueUnknown === 'string') {
      console.log(valueUnknown.toUpperCase());
    }
    
    
  • never類型:表示永遠不會返回的值,比如一個總是拋出錯誤的函數。

    示例代碼:

    function errorFunction(): never {
      throw new Error("Error message");
    }
    
    

使用這些類型可以幫助開發者在編寫代碼時提供更明確的意圖,並且讓 TypeScript 編譯器在編譯時期幫助捕捉潛在的錯誤。

第四章:介面與類型註解

在TypeScript中,介面(Interfaces)和類型註解(Type Annotations)是核心特性,它們允許開發者定義代碼的形狀和類型,以確保類型安全和代碼的可維護性。

介面的定義與使用

介面是對一組屬性進行抽象和封裝的一種方式。它定義了一個對象應有的結構,即它應該有哪些屬性以及這些屬性的類型。

  • 介面的定義

    interface User {
      name: string;
      age: number;
      readonly id: number; // 只讀屬性
      greet?(message: string): void; // 可選方法
    }
    
    
  • 介面的實現

    const user: User = {
      name: "張三",
      age: 30,
      id: 1,
      greet(message: string) {
        console.log(message);
      }
    };
    
    

介面也可以擴展其他介面,這意味著介面可以繼承另一個介面的屬性。

  • 介面的擴展

    interface Admin extends User {
      isAdmin: boolean;
    }
    
    

函數的類型註解

在TypeScript中,函數的參數和返回值都可以有類型註解,這有助於明確函數期望接收的數據類型以及函數應該返回的數據類型。

  • 函數的類型註解

    function add(a: number, b: number): number {
      return a + b;
    }
    
    

如果函數沒有返回值,可以使用void類型註解。

  • 無返回值的函數

    function log(message: string): void {
      console.log(message);
    }
    
    

類的類型註解

在TypeScript中,類也可以使用介面來註解。這可以確保類的實例符合介面定義的結構。

  • 類的類型註解

    interface Person {
      name: string;
      age: number;
      greet(): string;
    }
    
    class Developer implements Person {
      name: string;
      age: number;
    
      constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
      }
    
      greet() {
        return `Hello, my name is ${this.name}`;
      }
    }
    
    

在上述代碼中,Developer類實現了Person介面,這意味著Developer類的實例必須包含Person介面中定義的所有屬性和方法。

通過使用介面和類型註解,TypeScript 能夠在編譯時提供強類型檢查,從而減少運行時錯誤,並提高代碼的可靠性。

第五章:高級類型與泛型

TypeScript 的高級類型和泛型是其強大的類型系統的關鍵組成部分,允許開發者創建靈活且可重用的代碼。

高級類型

高級類型包括條件類型、映射類型等,這些類型為類型系統增加了更多的表達能力和靈活性。

  • 條件類型

    條件類型允許基於另一個類型來決定類型。

    type TypeName<T> = T extends string ? "string" :
                        T extends number ? "number" :
                        T extends boolean ? "boolean" :
                        "object";
    
    
  • 映射類型

    映射類型可以將一個已知的類型映射到另一個類型。

    type KeysOfObject<T> = {
      [K in keyof T]: T[K];
    };
    
    

泛型的基本概念

泛型是TypeScript的核心特性之一,允許在不確定類型的情況下編寫代碼。它通過類型參數(如T)來定義類型,在代碼使用時再指定具體的類型。

  • 泛型的定義

    function identity<T>(arg: T): T {
      return arg;
    }
    
    

在上面的例子中,identity函數是泛型的,它接收一個類型參數T,並返回同類型的值。

泛型在函數中的應用

泛型函數可以接收任何類型的參數,並返回相應的類型。

  • 泛型函數

    function loggingIdentity<T>(arg: T): T {
      // ...使用arg
      return arg;
    }
    
    

泛型在介面中的應用

泛型介面可以定義具有泛型類型的介面。

  • 泛型介面

    interface GenericIdentityFn<T> {
      (arg: T): T;
    }
    
    function identity<T>(arg: T): T {
      return arg;
    }
    
    let myIdentity: GenericIdentityFn<number> = identity;
    
    

在上面的例子中,GenericIdentityFn是一個泛型介面,myIdentity是一個將T約束為number的實例。

泛型在類中的應用

泛型類可以定義具有泛型類型的類。

  • 泛型類

    class GenericNumber<T> {
      zeroValue: T;
      add: (x: T, y: T) => T;
    }
    
    let myGenericNumber = new GenericNumber<number>();
    myGenericNumber.zeroValue = 0;
    myGenericNumber.add = function(x, y) { return x + y; };
    
    

在上面的例子中,GenericNumber是一個泛型類,它有一個泛型屬性zeroValue和一個泛型方法add

泛型在TypeScript中的應用非常廣泛,它們提供了一種創建可重用組件的方法,同時保持了類型安全。通過使用泛型,開發者可以編寫出更加靈活、可維護和可擴展的代碼。

第六章:Vue組件的類型化

在Vue中,使用TypeScript可以提供類型安全,並幫助開發者在開發組件時避免許多錯誤。以下是如何在Vue組件中使用TypeScript進行類型化的基本概念。

Vue組件的TypeScript支持

Vue 3從一開始就內置了對TypeScript的支持。你可以直接在.vue文件中使用TypeScript,Vue的編譯器會正確地處理這些文件。

  • 基礎Vue組件

    <script setup lang="ts">
    import { ref } from 'vue';
    
    const count = ref(0);
    </script>
    
    <template>
      <div>{{ count }}</div>
    </template>
    
    

<script setup>標簽中,你可以使用TypeScript的所有特性。

Prop的類型定義

在Vue組件中,props是外部傳入組件的數據。在TypeScript中,你可以為props定義類型。

  • Prop類型定義

    <script lang="ts">
    import { defineComponent } from 'vue';
    
    export default defineComponent({
      props: {
        title: String,
        value: {
          type: Number,
          default: 0
        },
        // 使用 TypeScript 的介面定義複雜類型
        author: {
          type: Object as () => Author,
          default: () => ({ name: 'Unknown' })
        }
      }
    });
    
    interface Author {
      name: string;
      age?: number;
    }
    </script>
    
    

Emit的類型定義

在Vue組件中,emit是用來向父組件發送事件的。你可以為emit定義類型,以確保發送的數據類型是正確的。

  • Emit類型定義

    <script lang="ts">
    import { defineComponent } from 'vue';
    
    export default defineComponent({
      emits: {
        // 使用字元串定義簡單的事件類型
        'update:title': String,
        // 使用 TypeScript 的介面定義複雜的事件類型
        'update:author': (author: Author) => boolean
      }
    });
    
    interface Author {
      name: string;
      age?: number;
    }
    </script>
    
    

組件方法的類型定義

組件方法也需要類型定義,以確保方法的輸入和輸出都是預期的類型。

  • 組件方法的類型定義

    <script lang="ts">
    import { defineComponent } from 'vue';
    
    export default defineComponent({
      methods: {
        updateTitle(title: string): void {
          // 更新標題的邏輯
        },
        increment(count: number): number {
          // 增加計數的邏輯
          return count + 1;
        }
      }
    });
    </script>
    
    

在上述代碼中,updateTitle方法接收一個string類型的參數,並且沒有返回值(void)。increment方法接收一個number
類型的參數,並返回一個number類型的值。

通過在Vue組件中應用TypeScript類型化,你可以獲得更強大的類型檢查和代碼提示,從而提高代碼質量和開發效率。

第七章:Vuex狀態管理的TypeScript集成

Vuex 是一個專為 Vue.js 應用程式開發的狀態管理模式和庫。當與 TypeScript 集成時,Vuex 的類型安全性可以大大提高,以下是如何在
Vuex 中使用 TypeScript 的基本概念和步驟。

Vuex的基本概念

Vuex 提供了一個集中存儲所有組件的狀態的方式,並以相應的規則保證狀態以一種可預測的方式發生變化。主要包括以下幾個部分:

  • State:定義了應用的狀態對象。
  • Getters:可以視作 store 的計算屬性,用於派生出一些狀態。
  • Mutations:更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。
  • Actions:類似於 mutation,但是用來處理非同步操作。

使用TypeScript定義Vuex的狀態、getter、mutation和action

在 TypeScript 中,你需要為 Vuex 的每個部分定義類型。

  • 定義狀態(State)

    interface State {
      count: number;
      name: string;
    }
    
    
  • 定義getter

    const getters = {
      doubleCount: (state: State) => state.count * 2
    };
    
    
  • 定義mutation

    const mutations = {
      increment(state: State, payload: { num: number }) {
        state.count += payload.num;
      }
    };
    
    
  • 定義action

    const actions = {
      incrementAsync({ commit }: { commit: Commit }, payload: { num: number }) {
        setTimeout(() => {
          commit('increment', payload);
        }, 1000);
      }
    };
    
    
  • 創建Vuex store

    import { createStore } from 'vuex';
    
    const store = createStore({
      state: {
        count: 0,
        name: 'Vuex'
      },
      getters,
      mutations,
      actions
    });
    
    

Vuex模塊化與TypeScript

在實際的大型項目中,通常會將 Vuex store 模塊化,而 TypeScript 則可以幫助我們保持模塊的類型安全。

  • 模塊化定義

    // store/modules/user.ts
    export interface UserState {
      id: number;
      name: string;
    }
    
    export default {
      namespaced: true,
      state: (): UserState => ({
        id: 1,
        name: 'User'
      }),
      getters: {
        userId(state: UserState) {
          return state.id;
        }
      },
      mutations: {
        updateName(state: UserState, newName: string) {
          state.name = newName;
        }
      },
      actions: {
        updateNameAsync({ commit }: { commit: Commit }, newName: string) {
          setTimeout(() => {
            commit('updateName', newName);
          }, 1000);
        }
      }
    };
    
    
  • 在主 store 文件中引入模塊

    import { createStore } from 'vuex';
    import userModule from './modules/user';
    
    const store = createStore({
      modules: {
        user: userModule
      }
    });
    
    

使用 TypeScript 與 Vuex 集成,可以確保你的 store 的狀態、getter、mutation 和 action 都有明確的類型定義,從而使得代碼更加健壯,易於維護。

第八章:Vue路由的TypeScript支持

Vue Router 是 Vue.js 的官方路由管理器。它與 Vue.js 核心深度集成,使得構建單頁面應用變得易如反掌。當與 TypeScript 結合使用時,Vue
Router 可以提供更好的類型檢查和自動補全,從而提高開發效率和代碼質量。

Vue Router的基本使用

在開始使用 TypeScript 之前,首先需要瞭解 Vue Router 的基本使用方法。

  • 安裝 Vue Router

    npm install vue-router
    
    
  • 創建路由實例

    import { createRouter, createWebHistory } from 'vue-router';
    import Home from './views/Home.vue';
    import About from './views/About.vue';
    
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About }
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes
    });
    
    
  • 在 Vue 應用中使用路由

    import { createApp } from 'vue';
    import App from './App.vue';
    import router from './router';
    
    const app = createApp(App);
    app.use(router);
    app.mount('#app');
    
    

路由配置的類型定義

在 TypeScript 中,你可以為路由配置定義類型,以確保路由的正確性和類型安全。

  • 定義路由配置類型

    interface RouteConfig {
      path: string;
      component: any; // 這裡應該使用具體的組件類型,例如 `typeof import('./views/Home.vue')`
    }
    
    const routes: RouteConfig[] = [
      { path: '/', component: import('./views/Home.vue') },
      { path: '/about', component: import('./views/About.vue') }
    ];
    
    
  • 創建路由實例

    import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
    
    const routes: Array<RouteRecordRaw> = [
      { path: '/', component: import('./views/Home.vue') },
      { path: '/about', component: import('./views/About.vue') }
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes
    });
    
    

路由守衛的類型註解

Vue Router 提供了多種路由守衛,如beforeEachbeforeResolveafterEach等,用於控制路由的跳轉。在 TypeScript
中,你可以為這些守衛函數添加類型註解。

  • 全局前置守衛

    import { NavigationGuardNext, RouteLocationNormalized } from 'vue-router';
    
    router.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
      // 在這裡添加路由守衛邏輯
      next();
    });
    
    
  • 組件內的守衛

    import { NavigationGuardNext, RouteLocationNormalizedLoaded } from 'vue-router';
    
    export default {
      beforeRouteEnter(to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded, next: NavigationGuardNext) {
        // 在渲染該組件的對應路由被驗證前調用
        next();
      }
    };
    
    

通過為 Vue Router 的路由配置和守衛函數添加類型註解,可以確保路由的正確性,並且在編譯時捕獲潛在的錯誤,從而提高代碼的健壯性和可維護性。
AD:覆蓋廣泛主題工具可供使用

第九章:構建一個TypeScript驅動的Vue應用

在構建一個 TypeScript 驅動的 Vue 應用時,我們需要考慮應用的架構設計、組件的編寫方式以及狀態的集中管理。以下是構建此類應用的步驟和指南。

應用設計思路與架構

在開始編碼之前,設計一個清晰的應用架構是非常重要的。

  • 設計思路

    • 確定應用的核心功能。
    • 分析應用的狀態管理需求。
    • 設計組件和頁面結構。
    • 確定服務層的介面和職責。
  • 架構

    • 前端架構:選擇 Vue 3 作為框架,結合 TypeScript 提供類型安全。
    • 狀態管理:使用 Vuex 進行狀態管理。
    • 路由管理:使用 Vue Router 管理頁面路由。
    • 服務層:負責與後端 API 通信,可以使用 Axios 等庫。

使用TypeScript編寫Vue組件

使用 TypeScript 編寫 Vue 組件可以提供類型檢查和代碼自動補全。

  • 組件類型定義

    import { defineComponent, PropType } from 'vue';
    
    interface MyComponentProps {
      title: string;
      items: Array<{ id: number; name: string }>;
    }
    
    export default defineComponent({
      name: 'MyComponent',
      props: {
        title: {
          type: String,
          required: true,
        },
        items: {
          type: Array as PropType<MyComponentProps['items']>,
          default: () => [],
        },
      },
      // 組件的其他選項和邏輯...
    });
    
    
  • 組件模板

    <template>
      <div>
        <h1>{{ title }}</h1>
        <ul>
          <li v-for="item in items" :key="item.id">{{ item.name }}</li>
        </ul>
      </div>
    </template>
    

集成Vuex和Vue Router

在 TypeScript 中集成 Vuex 和 Vue Router 需要正確地定義類型。

  • 集成 Vuex

    import { createStore } from 'vuex';
    
    interface State {
      count: number;
    }
    
    const store = createStore<State>({
      state: () => ({
        count: 0,
      }),
      mutations: {
        increment(state) {
          state.count++;
        },
      },
      actions: {
        increment({ commit }) {
          commit('increment');
        },
      },
    });
    
    
  • 集成 Vue Router

    import { createRouter, createWebHistory } from 'vue-router';
    import Home from './views/Home.vue';
    import About from './views/About.vue';
    
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About },
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes,
    });
    
    
  • 在 Vue 應用中使用

    import { createApp } from 'vue';
    import App from './App.vue';
    import store from './store';
    import router from './router';
    
    const app = createApp(App);
    app.use(store);
    app.use(router);
    app.mount('#app');
    
    

測試與調試

測試和調試是確保應用質量的重要步驟。

  • 單元測試:使用 Jest 或 Vue Test Utils 對組件進行單元測試。

    import { shallowMount } from '@vue/test-utils';
    import MyComponent from './MyComponent.vue';
    
    describe('MyComponent', () => {
      it('renders title and items', () => {
        const wrapper = shallowMount(MyComponent, {
          props: {
            title: 'Hello',
            items: [{ id: 1, name: 'Item 1' }],
          },
        });
        expect(wrapper.text()).toContain('Hello');
        expect(wrapper.text()).toContain('Item 1');
      });
    });
    
    
  • 集成測試:測試組件之間的交互和路由。

  • 端到端測試:使用 Cypress 或 Nightwatch 進行端到端測試。

  • 調試:使用 Vue Devtools 進行應用調試,檢查組件的狀態和路由。

通過以上步驟,可以構建一個結構清晰、類型安全、易於維護的 TypeScript 驅動的 Vue 應用。

第十章:性能優化與代碼分割

在開發 TypeScript 與 Vue 的應用程式時,性能優化和代碼分割是提升用戶體驗的重要方面。以下是性能優化和代碼分割的相關策略。

TypeScript與Vue的性能優化策略

  1. 類型檢查優化

    • 在開發環境中使用--strictNullChecks和其他類型檢查選項,但在生產環境構建時移除這些類型檢查,以減少運行時的負擔。
  2. 使用非同步組件

    • 將不是立即需要的組件轉換為非同步組件,這樣可以延遲它們的載入,直到真正需要時才載入。
  3. 虛擬滾動

    • 對於長列表數據,使用虛擬滾動來渲染可視範圍內的項,而不是渲染整個列表。
  4. 使用 Keep-alive 緩存組件

    • 對於那些不需要頻繁重新渲染的組件,使用<keep-alive>來緩存,以減少重渲染的性能開銷。
  5. 合理使用 computed 和 watch

    • 避免不必要的計算屬性和偵聽器,合理使用它們來避免不必要的計算和渲染。
  6. 使用 requestAnimationFrame

    • 對於動畫效果或頻繁更新的數據,使用requestAnimationFrame來優化,確保在瀏覽器下一次重繪之前更新。

代碼分割與懶載入

代碼分割是將代碼分成多個小塊,然後按需載入。Vue 提供了非同步組件和 Webpack 的動態導入功能來實現代碼分割和懶載入。

  • 動態導入

    const AsyncComponent = () => import('./components/AsyncComponent.vue');
    
    
  • 在路由中使用懶載入

    import { createRouter, createWebHistory } from 'vue-router';
    import Home from './views/Home.vue';
    
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: () => import('./views/About.vue') },
    ];
    
    const router = createRouter({
      history: createWebHistory(),
      routes,
    });
    
    

Tree Shaking與優化打包

Tree Shaking 是一種通過移除未引用代碼來優化打包體積的技術。

  1. 確保使用支持 Tree Shaking 的庫

    • 使用支持 ES2015 模塊語法的庫,這樣打包工具可以更容易地識別和搖樹。
  2. 配置 Webpack

    • 在 Webpack 配置中啟用mode: 'production',這會自動啟用 Tree Shaking。
    • 使用optimization.usedExports來僅打包那些真正被使用的模塊。
  3. 使用 externals

    • 將一些大型庫(如 Lodash 或 D3)設置為externals,這樣它們不會被包含在最終的打包文件中。
  4. 分析打包結果

    • 使用 Webpack 的stats-webpack-plugin或其他可視化工具來分析打包結果,查找可能的優化點。

通過以上策略,你可以顯著提升 TypeScript 與 Vue 應用的性能,並通過代碼分割和 Tree Shaking 來優化應用的載入時間和打包體積。
AD:享受無干擾的沉浸式閱讀之旅

附錄A:TypeScript與Vue的常見問題

常見錯誤與解決方案

  1. 錯誤:無法找到模塊 'vue' 或其相應的類型聲明文件

    • 解決方案:確保已經安裝了vue@vue/typescript相關的依賴,併在tsconfig.json中包含了vue的類型聲明。
  2. 錯誤:對象字面量可能只指定已知屬性,並且 'someProp' 不在類型 'SomeType' 中

    • 解決方案:確保對象字面量中的屬性與介面或類型定義中的屬性一致,或者使用索引簽名[key: string]: any
  3. 錯誤:函數參數應該有類型註解

    • 解決方案:在函數參數旁邊加上類型註解,例如function myFunction(param: string) { ... }
  4. 錯誤:組件必須以 'PascalCase' 命名

    • 解決方案:確保組件的文件名和組件定義中的name選項都是 PascalCase 格式。
  5. 錯誤:無法編譯模板中的表達式,因為不能保證模板表達式中的變數是安全的

    • 解決方案:確保在模板中使用的變數都是已定義的,並且類型正確。

TypeScript配置常見問題

  1. 如何指定 JSX 的工廠函數

    • tsconfig.json中,你可以使用jsxFactory選項來指定 JSX 的工廠函數,例如:
    {
      "compilerOptions": {
        "jsxFactory": "Vue.createElement"
      }
    }
    
    
  2. 如何配置tslinteslint

    • 對於tslint,你需要安裝tslinttslint-config-standard等相關依賴,併在項目根目錄創建一個tslint.json配置文件。
    • 對於eslint,你需要安裝eslinteslint-plugin-vue@typescript-eslint/parser
      等相關依賴,併在項目根目錄創建一個.eslintrc.js配置文件。
  3. 如何配置路徑別名(alias)

    • tsconfig.json中,你可以使用paths選項來配置路徑別名,例如:
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"]
        }
      }
    }
    
    

    然後,在.eslintrc.jstslint.json中配置相應的別名解析。

  4. 如何排除某些文件或目錄

    • tsconfig.jsonexclude數組中指定要排除的文件或目錄,例如:
    {
      "exclude": [
        "node_modules",
        "dist",
        "**/*.spec.ts"
      ]
    }
    
    
  5. 如何指定 TypeScript 的嚴格模式

    • tsconfig.jsoncompilerOptions中設置stricttrue,這會啟用所有嚴格類型檢查選項:
    {
      "compilerOptions": {
        "strict": true
      }
    }
    
    

通過正確配置 TypeScript 和解決常見的錯誤,你可以更順利地開發 Vue 應用程式,並確保代碼的質量和性能。

附錄B:TypeScript資源與學習指南

TypeScript官方文檔與社區資源

推薦書籍

  • 《TypeScript 從入門到精通》

    • 適合初學者,全面介紹 TypeScript 的基礎知識。
    • 作者:李成蹊
  • 《TypeScript 高級編程》

    • 適合有一定基礎的讀者,深入探討 TypeScript 的高級特性。
    • 作者:張耀春
  • 《TypeScript 進階指南》

    • 介紹了 TypeScript 的進階知識,包括類型系統、模塊化等。
    • 作者:程勇

推薦博客


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 介紹 RT-Thread Studio是官方出品的一款專門針對RT-Thread嵌入式開發、部署、調試、測試的集成開發環境,它基於Eclipse開源項目開發,極大的提高了嵌入式開發者的開發效率,目前最新版本是2.26 下載 使用瀏覽器打開RT-Thread官網,選擇左上角資源點擊RT-Thread ...
  • 介紹 MCXN947 NXP FRDM-MCXN947開發板是一款基於MCXN947 MCU的低成本評估板,MCU集成了雙核Arm Cortex-M33微控制器和一個神經處理單元(NPU)。開發板由一個MCXN947控制器和一個64 Mbit外部串列快閃記憶體組成。該板還具有P3T1755DP I3C溫度 ...
  • 註意:本教程不適用舊版本,Mysql 8.4.0 和 舊版本,主從複製相關命令有所變化,具體區別請看文末參考 軟體版本 Docker:26.1.3 Mysql:8.4.0 GTID主從複製 1.準備主從兩台伺服器 2.兩台伺服器分別創建 docker-compose.yml 文件 services: ...
  • 引言 近年來,“Ops”一詞在 IT 運維領域的使用迅速增加。IT 運維正在向自動化過程轉變,以改善客戶交付。傳統的應用程式開發採用 DevOps 實施持續集成(CI)和持續部署(CD)。但對於數據密集型的機器學習和人工智慧(AI)應用,精確的交付和部署過程可能並不適用。 本文將定義不同的“Ops” ...
  • 歡迎查閱袋鼠雲第10期產品功能更新報告。本期,我們精心推出了72項新增和優化功能,致力於在數字化浪潮中為您提供更高效、更智能的服務。我們相信,這些新特性將為您的業務註入新活力,確保您在數字化轉型的每一步都堅實而有力。 以下為袋鼠雲產品功能更新報告第10期內容,更多探索,請繼續閱讀。 離線開發平臺 新 ...
  • HarmonyOS ArkTS組件 | Flex 以彈性方式佈局子組件的容器組件 學習記錄 前言:最近需要用到彈性佈局,記錄一下。(忽略圖片水印QAQ) 說明: Flex組件在渲染時存在二次佈局過程,因此在對性能有嚴格要求的場景下建議使用Column、Row代替。 Flex組件主軸預設不設置時撐滿父 ...
  • ARM 64中包含多種寄存器,下麵介紹一些常見的寄存器。 1 通用寄存器 ARM 64包含31個64bit寄存器,記為X0~X30。 每一個通用寄存器,它的低32bit都可以被訪問,記為W0~W30。 在這31個通用寄存器中,有2個寄存器比較特殊。 X29寄存器被作為棧幀寄存器,也被稱為FP(Fra ...
  • 前言 移動應用中的通知是指應用程式發送給用戶的一種提示或提醒消息。這些通知可以在用戶設備的通知中心或狀態欄中顯示,以提醒用戶有關應用程式的活動、事件或重要信息。 移動應用中的通知可以分為兩種類型:本地通知和遠程通知。 本地通知是由應用程式自身發起的通知,不需要連接到遠程伺服器。應用程式可以根據特 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...