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>
相关推荐
熊猫钓鱼>_>9 小时前
Vue3 + Tailwind CSS + DaisyUI 现代前端开发完全攻略
前端·css·vue.js·vue3·tailwind·daisyui·现代开发
前端码农一枚10 小时前
Vue3+TypeScript实现手机扫码功能
vue.js·typescript
小白_ysf11 小时前
Vue3+TS项目中高德地图组件封装(集成关键词搜索、输入提示、标记点、信息弹窗和数据回显)
vue3·ts·高德·地图 js api
Slow菜鸟16 小时前
微信小程序(TypeScript)开发指南
微信小程序·小程序·typescript
亮子AI17 小时前
【Typescript】未知类型如何处理?
linux·javascript·typescript
hboot1 天前
💪别再迷茫!一份让你彻底掌控 TypeScript 类型系统的终极指南
前端·typescript
Light601 天前
Vue 高阶优化术:v-bind 与 v-on 的实战妙用与思维跃迁
前端·低代码·vue3·v-bind·组件封装·v-on·ai辅助开发
1024肥宅1 天前
现代 JavaScript 特性:TypeScript 深度解析与实践
前端·javascript·typescript
开开心心_Every2 天前
优化C盘存储:自定义软件文档保存路径工具
java·网络·数据库·typescript·word·asp.net·excel
running up2 天前
Vite 全面解析:特性、对比、实践及最新演进
javascript·typescript