TS在Vue3中的使用实例集合

一、定义一个定时器

复制代码
  let timer: NodeJS.Timeout | null = null;

  const start = () => {
    if(timer) return;
    timer = setInterval(() => {
      if(count.value > 0){
        count.value--;
      } else{
        stop();
      }
    }, 1000)
  }

二、事件对象

复制代码
  const updateMouse = (event: MouseEvent) => {
    x.value = event.pageX
    y.value = event.pageY
  }

三、响应式状态(reactive/ref 类型)

ref:通过泛型指定类型(复杂类型推荐显式声明)。

reactive:通过接口定义对象结构。

复制代码
<script setup lang="ts">
import { ref, reactive } from 'vue'

// 复杂类型的 ref(显式泛型)
interface User {
  name: string
  age: number
  hobbies?: string[]
}
const user = ref<User>({ name: 'Alice', age: 20 })
user.value.age = '20' // 错误:age 应为 number

// reactive 对象(通过接口约束)
const form = reactive({
  username: '',
  password: ''
})
form.username = 123 // 错误:应为 string
</script>

四、计算属性(computed)

计算属性的返回值类型会自动推断,也可显式指定。

复制代码
<script setup lang="ts">
import { ref, computed } from 'vue'

const list = ref([1, 2, 3, 4])

// 自动推断:number
const total = computed(() => {
  return list.value.reduce((sum, item) => sum + item, 0)
})

// 显式指定类型(复杂场景)
interface FilteredItem {
  id: number
  active: boolean
}
const items = ref<FilteredItem[]>([
  { id: 1, active: true },
  { id: 2, active: false }
])
const activeItems = computed<FilteredItem[]>(() => {
  return items.value.filter(item => item.active)
})
</script>

五、生命周期钩子与函数参数

钩子函数的参数类型(如 onMounted 无参数,onBeforeUpdate 接收 DOM 快照)会自动提示。

复制代码
<script setup lang="ts">
import { onMounted, onBeforeUpdate, ref } from 'vue'

const el = ref<HTMLDivElement | null>(null)

onMounted(() => {
  // el.value 类型:HTMLDivElement | null
  if (el.value) {
    el.value.scrollTop = 0 // 正确:只有 DOM 元素有 scrollTop
  }
})

onBeforeUpdate((prevVnode) => {
  // prevVnode 类型:VNode (Vue 内部类型)
  console.log('Previous VNode:', prevVnode)
})
</script>

<template>
  <div ref="el">内容</div>
</template>

六、Hook中使用

复制代码
// src/composables/useCounter.ts
import { ref } from 'vue'

export function useCounter(initialValue: number = 0) {
  const count = ref<number>(initialValue)

  const increment = (): void => {
    count.value++
  }

  const decrement = (): void => {
    count.value--
  }

  return {
    count,
    increment,
    decrement,
  }
}

七、defineProps中使用

在 TS 环境中,可通过类型注解声明 props,更简洁且类型安全:

复制代码
<template>
  <div>{{ name }} - {{ age }}</div>
</template>

<script setup lang="ts">
// 声明 props 类型
const props = defineProps<{
  name: string
  age?: number // 可选 prop(非必传)
}>()

// 访问时会有类型提示
console.log(props.name.toUpperCase())
</script>

带默认值的 TypeScript 写法

TS 类型声明中无法直接指定默认值,需配合 withDefaults 宏:

复制代码
<script setup lang="ts">
// 声明类型
interface Props {
  name: string
  age?: number
  hobbies?: string[]
}

// 指定默认值
const props = withDefaults(defineProps<Props>(), {
  age: 18,
  hobbies: () => ['coding', 'reading'] // 引用类型默认值需用函数返回
})

// 使用时,age 和 hobbies 会有默认值
console.log(props.age) // 18(若父组件未传递)
</script>

八、defineEmits使用

方式 1:对象类型(推荐)

键为事件名,值为事件回调函数的参数类型:

复制代码
<script setup lang="ts">
// 声明事件类型:
// - 'update' 事件:接收一个 string 类型参数
// - 'delete' 事件:接收两个参数(id: number, name: string)
const emits = defineEmits<{
  (e: 'update', value: string): void
  (e: 'delete', id: number, name: string): void
}>()

// 触发事件时,参数类型会被校验
const handleUpdate = () => {
  emits('update', 'new value') // 正确
  // emits('update', 123) // 错误:参数类型不匹配
}

const handleDelete = () => {
  emits('delete', 1, 'test') // 正确
}
</script>

方式 2:接口类型(简洁)

通过接口定义事件参数结构:

复制代码
<script setup lang="ts">
interface Emits {
  (e: 'change', val: boolean): void
  (e: 'submit', formData: { name: string; age: number }): void
}

const emits = defineEmits<Emits>()

// 触发 submit 事件时,参数需符合接口结构
emits('submit', { name: '张三', age: 20 }) // 正确
</script>

在父组件中使用

子组件声明的事件可在父组件中通过 v-on(或 @ 简写)监听:

复制代码
<!-- 父组件 -->
<template>
  <ChildComponent 
    @change="handleChildChange" 
    @submit="handleChildSubmit"
  />
</template>

<script setup>
const handleChildChange = (val: string) => {
  console.log('子组件触发了change:', val)
}

const handleChildSubmit = (formData: { name: string; age: number }) => {
  console.log('子组件触发了submit:', formData)
}
</script>

九、路由相关(Vue Router + TS)

定义路由参数、查询参数的类型,避免字符串拼写错误。

复制代码
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from './views/Home.vue'

// 定义路由参数类型
interface RouteParams {
  id: string // 动态路由参数:/user/:id
}

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/user/:id',
      component: () => import('./views/User.vue'),
      // 路由元信息类型
      meta: { requiresAuth: true } as { requiresAuth: boolean }
    }
  ]
})

export default router

在组件中使用:

复制代码
<!-- src/views/User.vue -->
<script setup lang="ts">
import { useRoute } from 'vue-router'

const route = useRoute()
// 路由参数类型:RouteParams["id"] 即 string
const userId = route.params.id // 类型:string

// 查询参数(显式指定类型)
const query = route.query as { page?: string; keyword?: string }
const currentPage = Number(query.page) || 1
</script>

十、状态管理(Pinia + TS)

Pinia 原生支持 TS,定义 Store 时可约束状态、 actions 类型。

复制代码
// src/stores/counter.ts
import { defineStore } from 'pinia'

// 定义 Store 类型
interface CounterState {
  count: number
  user: { name: string } | null
}

export const useCounterStore = defineStore('counter', {
  state: (): CounterState => ({
    count: 0,
    user: null
  }),
  actions: {
    increment(step: number) { // 显式指定参数类型
      this.count += step
    },
    setUser(name: string) {
      this.user = { name } // 符合 state 类型约束
    }
  }
})

在组件中使用:

复制代码
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()
store.increment(2) // 正确:参数为 number
// store.increment('2') // 错误:参数应为 number
console.log(store.user?.name) // 自动提示:可选链避免 null 错误
</script>
相关推荐
昨晚我输给了一辆AE8615 小时前
为什么现在不推荐使用 React.FC 了?
前端·react.js·typescript
Wect21 小时前
LeetCode 130. 被围绕的区域:两种解法详解(BFS/DFS)
前端·算法·typescript
Dilettante25821 小时前
这一招让 Node 后端服务启动速度提升 75%!
typescript·node.js
jonjia2 天前
模块、脚本与声明文件
typescript
jonjia2 天前
配置 TypeScript
typescript
jonjia2 天前
TypeScript 工具函数开发
typescript
jonjia2 天前
注解与断言
typescript
jonjia2 天前
IDE 超能力
typescript
jonjia2 天前
对象类型
typescript
jonjia2 天前
快速搭建 TypeScript 开发环境
typescript