最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3+TypeScript 常用代碼示例總結(jié)

 更新時(shí)間:2026年03月31日 08:29:43   作者:菜果果兒  
本文主要介紹了Vue3+TypeScript 常用代碼示例總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、TypeScript 內(nèi)置工具類型

1.1Partial? 的作用

Partial<T>是 TypeScript 內(nèi)置的工具類型,它可以將類型 T的所有屬性變?yōu)榭蛇x。

// Partial 的實(shí)現(xiàn)原理(簡化版)
type Partial<T> = {
  [P in keyof T]?: T[P];
};
// 使用示例
interface Theme {
  primaryColor: string;
  secondaryColor: string;
  fontSize: number;
}
// 正常 Theme 類型,所有屬性都是必需的
const theme1: Theme = {
  primaryColor: '#1890ff',
  secondaryColor: '#52c41a',
  fontSize: 14
};
// ? 所有屬性都必須提供
// 使用 Partial<Theme> 后,所有屬性都變?yōu)榭蛇x
const theme2: Partial<Theme> = {
  primaryColor: '#1890ff'
  // secondaryColor 和 fontSize 可以不提供
};
// ? 可以只提供部分屬性
// 在函數(shù)參數(shù)中使用 Partial
function updateTheme(theme: Partial<Theme>): void {
  // 可以只更新部分屬性
  // theme 可能只包含 primaryColor,或只包含 fontSize,或都包含
}
// 調(diào)用示例
updateTheme({ primaryColor: '#ff4d4f' }); // ? 只更新一個(gè)屬性
updateTheme({ fontSize: 16 }); // ? 只更新另一個(gè)屬性
updateTheme({}); // ? 傳遞空對象也可以

1.2 其他常用工具類型

// 1. Required<T> - 將可選屬性變?yōu)楸靥?
interface User {
  id: number;
  name?: string;  // 可選
  email?: string; // 可選
}
type RequiredUser = Required<User>;
// 等價(jià)于:
// {
//   id: number;
//   name: string;   // 變?yōu)楸靥?
//   email: string;  // 變?yōu)楸靥?
// }
// 2. Readonly<T> - 將所有屬性變?yōu)橹蛔x
type ReadonlyUser = Readonly<User>;
// 等價(jià)于:
// {
//   readonly id: number;
//   readonly name?: string;
//   readonly email?: string;
// }
// 3. Pick<T, K> - 從 T 中挑選部分屬性
type UserBasicInfo = Pick<User, 'id' | 'name'>;
// 等價(jià)于:
// {
//   id: number;
//   name?: string;
// }
// 4. Omit<T, K> - 從 T 中排除部分屬性
type UserWithoutId = Omit<User, 'id'>;
// 等價(jià)于:
// {
//   name?: string;
//   email?: string;
// }
// 5. Record<K, T> - 創(chuàng)建鍵值對類型
type UserMap = Record<string, User>;
// 等價(jià)于:
// {
//   [key: string]: User;
// }
// 6. Exclude<T, U> - 從 T 中排除可以賦值給 U 的類型
type T1 = 'a' | 'b' | 'c';
type T2 = 'a';
type Result = Exclude<T1, T2>; // 'b' | 'c'
// 7. Extract<T, U> - 從 T 中提取可以賦值給 U 的類型
type T3 = 'a' | 'b' | 'c';
type T4 = 'a' | 'd';
type Result2 = Extract<T3, T4>; // 'a'
// 8. NonNullable<T> - 排除 null 和 undefined
type T5 = string | number | null | undefined;
type Result3 = NonNullable<T5>; // string | number

二、Vue 3 中的類型

2.1ComputedRef? 類型

ComputedRef<T>是 Vue 3 中計(jì)算屬性的類型,它是 Ref<T>的子類型。

import { ref, computed, Ref, ComputedRef } from 'vue'
// 1. 基礎(chǔ)使用
const count = ref<number>(0); // Ref<number>
const doubleCount = computed(() => count.value * 2); // ComputedRef<number>
// 2. 顯式類型聲明
const doubleCount2: ComputedRef<number> = computed(() => count.value * 2);
// 3. 帶 getter 和 setter 的計(jì)算屬性
const fullName = computed<string>({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (value: string) => {
    const [first, last] = value.split(' ')
    firstName.value = first
    lastName.value = last || ''
  }
});
// 4. 在函數(shù)參數(shù)中使用
function logComputedValue(computedValue: ComputedRef<any>): void {
  console.log(computedValue.value);
}
logComputedValue(doubleCount);

2.2 Vue 3 常用類型

import {
  Ref,           // 響應(yīng)式引用類型
  ComputedRef,   // 計(jì)算屬性類型
  UnwrapRef,     // 解包響應(yīng)式類型
  MaybeRef,      // 可能是 Ref 或普通值
  MaybeRefOrGetter, // 可能是 Ref、getter 函數(shù)或普通值
  WritableComputedRef, // 可寫的計(jì)算屬性
  ShallowRef,    // 淺層 Ref
  ShallowReactive, // 淺層 reactive
  ToRefs,        // 將 reactive 轉(zhuǎn)換為 refs
  ComponentPublicInstance, // 組件實(shí)例類型
  VNode,         // 虛擬節(jié)點(diǎn)類型
  Component      // 組件類型
} from 'vue'
// 1. Ref 類型
const countRef: Ref<number> = ref(0);
// 2. UnwrapRef - 獲取 Ref 內(nèi)部的類型
type CountType = UnwrapRef<typeof countRef>; // number
// 3. MaybeRef - 接受 Ref 或普通值
function useDouble(value: MaybeRef<number>): ComputedRef<number> {
  return computed(() => {
    // 判斷是否是 Ref
    if (isRef(value)) {
      return value.value * 2
    }
    return value * 2
  });
}
// 或者使用 unref 工具函數(shù)
import { unref } from 'vue'
function useDouble2(value: MaybeRef<number>): ComputedRef<number> {
  return computed(() => unref(value) * 2);
}
// 4. ToRefs - 將 reactive 轉(zhuǎn)換為多個(gè) ref
interface State {
  count: number;
  name: string;
}
const state = reactive<State>({ count: 0, name: 'Vue' });
const stateRefs: ToRefs<State> = toRefs(state);
// 現(xiàn)在可以使用 stateRefs.count.value 和 stateRefs.name.value

三、實(shí)際應(yīng)用示例

3.1 表單組件示例

import { defineComponent, reactive, computed, toRefs } from 'vue'
// 表單數(shù)據(jù)類型
interface FormData {
  username: string
  email: string
  age: number | null
  agree: boolean
}
// 表單驗(yàn)證規(guī)則類型
type ValidationRule = (value: any) => string | true
interface FormRules {
  [key: string]: ValidationRule | ValidationRule[]
}
export default defineComponent({
  setup() {
    // 表單數(shù)據(jù)
    const formData = reactive<FormData>({
      username: '',
      email: '',
      age: null,
      agree: false
    })
    // 表單驗(yàn)證規(guī)則
    const rules: FormRules = {
      username: [
        (value: string) => !!value || '用戶名不能為空',
        (value: string) => value.length >= 3 || '用戶名至少3個(gè)字符'
      ],
      email: [
        (value: string) => !!value || '郵箱不能為空',
        (value: string) => /.+@.+..+/.test(value) || '郵箱格式不正確'
      ],
      age: (value: number | null) => {
        if (value === null) return '年齡不能為空'
        if (value < 0) return '年齡不能為負(fù)數(shù)'
        if (value > 150) return '年齡不能超過150歲'
        return true
      }
    }
    // 表單驗(yàn)證狀態(tài)
    const errors = reactive<Partial<Record<keyof FormData, string>>>({})
    // 驗(yàn)證單個(gè)字段
    const validateField = (field: keyof FormData): boolean => {
      const value = formData[field]
      const rule = rules[field]
      if (!rule) {
        delete errors[field]
        return true
      }
      const rulesArray = Array.isArray(rule) ? rule : [rule]
      for (const validate of rulesArray) {
        const result = validate(value)
        if (typeof result === 'string') {
          errors[field] = result
          return false
        }
      }
      delete errors[field]
      return true
    }
    // 驗(yàn)證整個(gè)表單
    const validateForm = (): boolean => {
      let isValid = true
      Object.keys(formData).forEach(field => {
        if (!validateField(field as keyof FormData)) {
          isValid = false
        }
      })
      return isValid
    }
    // 提交表單
    const submitForm = (): void => {
      if (!validateForm()) {
        console.log('表單驗(yàn)證失敗')
        return
      }
      console.log('提交表單:', formData)
      // 這里可以調(diào)用 API
    }
    // 重置表單
    const resetForm = (): void => {
      Object.assign(formData, {
        username: '',
        email: '',
        age: null,
        agree: false
      })
      Object.keys(errors).forEach(key => {
        delete errors[key as keyof typeof errors]
      })
    }
    // 計(jì)算屬性:表單是否有效
    const isFormValid = computed<boolean>(() => {
      return Object.keys(errors).length === 0 &&
        formData.username !== '' &&
        formData.email !== '' &&
        formData.age !== null &&
        formData.agree
    })
    return {
      // 使用 toRefs 保持響應(yīng)性
      ...toRefs(formData),
      errors,
      isFormValid,
      validateField,
      validateForm,
      submitForm,
      resetForm
    }
  }
})

3.2 使用工具類型的通用函數(shù)

// utils/types.ts
// 自定義工具類型
// 1. 深度可選類型
type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
// 2. 深度只讀類型
type DeepReadonly<T> = {
  readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
// 3. 可空類型
type Nullable<T> = T | null | undefined;
// 4. 提取函數(shù)返回類型
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
// 5. 提取函數(shù)參數(shù)類型
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
// 6. 提取 Promise 的返回值類型
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
// 使用示例
interface User {
  id: number;
  name: string;
  profile: {
    avatar: string;
    bio: string;
  };
  tags: string[];
}
// 深度可選
type PartialUser = DeepPartial<User>;
// 可以這樣使用:
const user1: PartialUser = {
  name: '張三',
  profile: {
    avatar: 'avatar.jpg'
    // bio 可以不提供
  }
  // tags 可以不提供
};
// 深度只讀
type ReadonlyUser = DeepReadonly<User>;
const user2: ReadonlyUser = {
  id: 1,
  name: '李四',
  profile: {
    avatar: 'avatar.jpg',
    bio: 'Hello'
  },
  tags: ['a', 'b']
};
// user2.profile.bio = 'World'; // ? 錯(cuò)誤:不能修改只讀屬性
// 可空類型
let nullableString: Nullable<string> = 'Hello';
nullableString = null; // ?
nullableString = undefined; // ?

3.3 組合式函數(shù)的類型

// composables/useFetch.ts
import { ref, computed, Ref, ComputedRef } from 'vue'
// 請求狀態(tài)類型
type FetchStatus = 'idle' | 'loading' | 'success' | 'error'
// 返回類型
interface UseFetchReturn<T> {
  data: Ref<T | null>
  error: Ref<string | null>
  status: Ref<FetchStatus>
  isLoading: ComputedRef<boolean>
  isSuccess: ComputedRef<boolean>
  isError: ComputedRef<boolean>
  execute: (url: string, options?: RequestInit) => Promise<void>
  reset: () => void
}
// 選項(xiàng)類型
interface UseFetchOptions {
  immediate?: boolean
  initialData?: any
}
export function useFetch<T = any>(
  initialUrl?: string,
  options: UseFetchOptions = {}
): UseFetchReturn<T> {
  const { immediate = false, initialData = null } = options
  const data = ref<T | null>(initialData) as Ref<T | null>
  const error = ref<string | null>(null)
  const status = ref<FetchStatus>('idle')
  const isLoading = computed(() => status.value === 'loading')
  const isSuccess = computed(() => status.value === 'success')
  const isError = computed(() => status.value === 'error')
  const execute = async (url: string, requestOptions?: RequestInit): Promise<void> => {
    status.value = 'loading'
    error.value = null
    try {
      const response = await fetch(url, requestOptions)
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`)
      }
      const result = await response.json()
      data.value = result
      status.value = 'success'
    } catch (err) {
      error.value = err instanceof Error ? err.message : '請求失敗'
      status.value = 'error'
    }
  }
  const reset = (): void => {
    data.value = initialData
    error.value = null
    status.value = 'idle'
  }
  // 立即執(zhí)行
  if (immediate && initialUrl) {
    execute(initialUrl)
  }
  return {
    data,
    error,
    status,
    isLoading,
    isSuccess,
    isError,
    execute,
    reset
  }
}
// 在組件中使用
import { defineComponent, onMounted } from 'vue'
interface Post {
  id: number
  title: string
  body: string
  userId: number
}
export default defineComponent({
  setup() {
    // 使用 useFetch
    const { 
      data: posts, 
      error, 
      isLoading, 
      isSuccess, 
      execute 
    } = useFetch<Post[]>('https://jsonplaceholder.typicode.com/posts')
    // 或者延遲執(zhí)行
    const { 
      data: user, 
      execute: fetchUser 
    } = useFetch<Post>(undefined, { immediate: false })
    onMounted(() => {
      // 手動(dòng)執(zhí)行
      fetchUser('https://jsonplaceholder.typicode.com/posts/1')
    })
    // 重新獲取
    const refresh = (): void => {
      execute('https://jsonplaceholder.typicode.com/posts')
    }
    return {
      posts,
      error,
      isLoading,
      isSuccess,
      refresh
    }
  }
})

四、常見問題解答

Q1: 什么時(shí)候用Partial?

A: ? 當(dāng)你需要?jiǎng)?chuàng)建一個(gè)對象,它包含原始類型的一部分屬性時(shí)使用。

// 更新用戶信息時(shí),通常只需要更新部分字段
interface User {
  id: number
  name: string
  email: string
  age: number
}
function updateUser(userId: number, updates: Partial<User>): void {
  // updates 可以只包含 name,或只包含 email,或任意組合
  // 但不會(huì)包含不存在的屬性
}

Q2:ComputedRef和普通Ref有什么區(qū)別?

A: ? 主要區(qū)別:

  • ComputedRef是只讀的,你不能直接修改它的值
  • ComputedRef的值是通過計(jì)算得到的
  • 你可以為 ComputedRef提供 setter,但通常不建議
// Ref - 可以直接修改
const count = ref(0)
count.value = 1  // ? 可以
// ComputedRef - 默認(rèn)只讀
const double = computed(() => count.value * 2)
double.value = 4  // ? 錯(cuò)誤:不能直接修改計(jì)算屬性
// 帶 setter 的 ComputedRef
const fullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (value) => {
    const [first, last] = value.split(' ')
    firstName.value = first
    lastName.value = last || ''
  }
})

Q3: 什么時(shí)候需要顯式指定類型?

A: ? TypeScript 有類型推斷,但以下情況建議顯式指定:

// 1. 函數(shù)參數(shù)和返回值
function add(a: number, b: number): number {
  return a + b
}
// 2. 復(fù)雜對象
interface Config {
  apiUrl: string
  timeout: number
  retry: boolean
}
const config: Config = {
  apiUrl: '/api',
  timeout: 5000,
  retry: true
}
// 3. 組件 Props
interface Props {
  title: string
  count: number
  items: Array<{ id: number; name: string }>
}
// 4. API 響應(yīng)
interface ApiResponse<T = any> {
  code: number
  data: T
  message: string
}
async function fetchUser(id: number): Promise<ApiResponse<User>> {
  const response = await fetch(`/api/users/${id}`)
  return response.json()
}

記住:TypeScript 的核心價(jià)值在于類型安全,良好的類型定義能幫助你在編碼階段就發(fā)現(xiàn)潛在的錯(cuò)誤,提高代碼質(zhì)量和開發(fā)效率。

到此這篇關(guān)于Vue3+TypeScript 常用代碼示例總結(jié)的文章就介紹到這了,更多相關(guān)Vue3 TypeScript示例內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

纳雍县| 东至县| 高密市| 平遥县| 柳林县| 沂水县| 洞口县| 济源市| 绥芬河市| 涟源市| 原阳县| 浦江县| 浮梁县| 调兵山市| 河间市| 马尔康县| 昆明市| 淮阳县| 襄垣县| 合江县| 平阳县| 石河子市| 赤壁市| 双城市| 延川县| 诸暨市| 易门县| 灯塔市| 班戈县| 南京市| 剑河县| 库伦旗| 获嘉县| 天水市| 噶尔县| 五原县| 寿宁县| 江达县| 建昌县| 龙海市| 商水县|