news 2026/5/1 8:53:27

Vue3如何融合TS

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3如何融合TS

Vue3 对 TS 的适配是全方位的,从组件定义、Props 声明到响应式数据、生命周期等都有专门的 TS 语法,下面我会按开发中最常用的场景逐一讲解:

一、基础:组件的 TS 写法(setup 语法糖)

Vue3 推荐使用<script setup lang="ts">作为 TS 组件的核心写法,这是对 TS 支持最友好的方式,也是官方推荐的最佳实践。

<template> <div>{{ msg }}</div> <button @click="handleClick">点击</button> </template> <script setup lang="ts"> // 1. 响应式数据的 TS 类型标注 import { ref, reactive } from 'vue' // ref 基础类型(TS 可自动推导,也可显式标注) const msg = ref<string>('Hello Vue3 + TS') // 显式标注为字符串类型 const count = ref(0) // 自动推导为 number 类型 // reactive 复杂类型(推荐用 interface/type 定义) interface User { name: string age: number isAdmin?: boolean // 可选属性 } const user = reactive<User>({ name: '张三', age: 20 }) // 2. 函数的 TS 类型标注 const handleClick = (): void => { // 无返回值标注为 void count.value++ console.log(count.value) } </script>

二、核心:Props 的 TS 强类型声明

Vue3 提供了defineProps专门适配 TS 的写法,有两种方式(推荐第二种):

方式 1:运行时声明(兼容 Vue2 风格,类型推导)
<script setup lang="ts"> // TS 会自动从 props 定义中推导类型 const props = defineProps({ title: { type: String, required: true }, size: { type: Number, default: 16 }, isShow: Boolean }) // 使用 props 时会有完整的类型提示 console.log(props.title) // 提示为 string 类型 </script>
方式 2:纯 TS 类型声明(推荐,更贴合 TS 习惯)
<script setup lang="ts"> // 用 TS 接口定义 Props 类型,配合 withDefaults 设置默认值 interface Props { title: string // 必传 size?: number // 可选 isShow?: boolean // 可选 } // 方式 1:仅声明类型 // const props = defineProps<Props>() // 方式 2:声明类型 + 设置默认值(推荐) const props = withDefaults(defineProps<Props>(), { size: 16, isShow: true }) </script>

三、Emits 的 TS 类型声明

defineEmits同样支持 TS 类型标注,明确事件的名称和参数类型:

<script setup lang="ts"> // 方式 1:纯 TS 类型声明(推荐) const emit = defineEmits<{ // 事件名: (参数1类型, 参数2类型) => void change: (value: string) => void confirm: (id: number, name: string) => void }>() // 方式 2:运行时声明(类型推导) // const emit = defineEmits(['change', 'confirm']) // 触发事件时会校验参数类型 const handleConfirm = () => { emit('confirm', 1, '张三') // 正确 // emit('confirm', '1', '张三') // TS 报错:id 应为 number 类型 } </script>

四、Ref 获取 DOM 元素的 TS 标注

获取 DOM 元素时,需要给 ref 标注具体的元素类型:

<template> <input ref="inputRef" type="text" /> </template> <script setup lang="ts"> import { ref, onMounted } from 'vue' // 标注为 HTMLInputElement 类型,初始值为 null const inputRef = ref<HTMLInputElement | null>(null) onMounted(() => { // 使用时需要判空(避免 null 报错) if (inputRef.value) { inputRef.value.focus() // TS 会提示 input 元素的所有方法/属性 } }) </script>

五、组合式函数的 TS 适配

自定义组合式函数时,通过 TS 标注返回值类型,让调用方获得完整提示:

// hooks/useUser.ts import { ref, computed } from 'vue' interface UserInfo { id: number name: string } // 标注函数返回值类型 export function useUser(): { user: Ref<UserInfo | null> userName: ComputedRef<string> updateName: (name: string) => void } { const user = ref<UserInfo | null>(null) const userName = computed(() => { return user.value?.name || '未知用户' }) const updateName = (name: string): void => { if (user.value) { user.value.name = name } } return { user, userName, updateName } }

在组件中使用:

<script setup lang="ts"> import { useUser } from '@/hooks/useUser' // 解构时会获得完整的类型提示 const { user, userName, updateName } = useUser() </script>

六、全局属性 / 方法的 TS 扩展

如果给 Vue 实例添加了全局属性(如app.config.globalProperties.$api),需要扩展 TS 类型以获得提示:

// src/types/global.d.ts import type { ComponentCustomProperties } from 'vue' import type { Api } from '@/api' // 扩展 ComponentCustomProperties 接口 declare module 'vue' { interface ComponentCustomProperties { $api: Api // 声明全局 $api 的类型 $formatTime: (time: number) => string // 声明全局方法类型 } }

总结

Vue3 对 TS 的核心适配语法可以总结为以下 3 个关键点:

  1. 核心基座:使用<script setup lang="ts">作为 TS 组件的基础,这是所有适配语法的前提。
  2. 核心 APIdefineProps<Props>()withDefaults()defineEmits<Emits>()是组件层面适配 TS 的核心,能精准约束 Props/Emits 类型。
  3. 类型标注:响应式数据(ref/reactive)、DOM 引用、组合式函数等场景,通过 TS 的interface/type+ 显式标注,实现完整的类型校验和代码提示。

这些语法的核心目标是让 Vue 组件的每一个部分(数据、Props、事件、方法)都能被 TS 精准识别,既提升开发效率,也减少运行时错误。

vue3中父子同行

你想了解的是 Vue3 中父子组件在同一行显示的布局实现方法,这本质上是 CSS 布局的问题,Vue3 本身不直接控制布局,但可以结合 Vue 的组件写法来实现这个效果。

下面我会提供几种最常用、兼容性最好的实现方案,你可以根据实际需求选择:

一、核心实现思路(Flex 布局,推荐)

Flex 布局是实现 “父子同行” 最简洁、灵活的方式,也是现代前端布局的首选方案。

1. 基础示例(父组件控制布局)
<!-- 父组件 Parent.vue --> <template> <!-- 父容器设置 display: flex 即可让子元素同行 --> <div class="parent-container"> <!-- 子组件1 --> <Child1 /> <!-- 子组件2 --> <Child2 /> <!-- 普通元素也适用 --> <div class="normal-element">普通元素</div> </div> </template> <script setup lang="ts"> import

父子通信

你想了解的是 Vue3 中父子组件之间的通信方式,这是 Vue 开发中最基础也最核心的知识点之一,Vue3 结合 TypeScript 提供了更规范、类型更安全的通信方案。

下面我会按「父传子」「子传父」「父子双向通信」「跨级 / 通用通信(补充)」四个维度,结合 TS 语法详细讲解,所有示例都基于 Vue3 推荐的<script setup lang="ts">语法。


一、父传子(Props)

这是最基础的通信方式,父组件通过 Props 向子组件传递数据,Vue3 + TS 下能通过类型校验保证数据合法性。

1. 子组件(Child.vue):声明 Props 并接收
<template> <div> <h3>子组件接收的父组件数据:</h3> <p>标题:{{ title }}</p> <p>数量:{{ count }}</p> <p>是否显示:{{ isShow }}</p> </div> </template> <script setup lang="ts"> // 1. 定义 Props 类型(TS 专属) interface Props { title: string; // 必传字符串 count?: number; // 可选数字 isShow?: boolean; // 可选布尔值 } // 2. 声明 Props + 设置默认值(withDefaults 是 Vue3 适配 TS 的语法) const props = withDefaults(defineProps<Props>(), { count: 0, // count 默认值 isShow: true // isShow 默认值 }); </script>
2. 父组件(Parent.vue):传递 Props
<template> <div class="parent"> <h2>父组件</h2> <!-- 向子组件传递 Props --> <Child title="父组件传递的标题" :count="parentCount" :isShow="parentIsShow" /> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; import Child from './Child.vue'; // 父组件的响应式数据 const parentCount = ref<number>(10); const parentIsShow = ref<boolean>(true); </script>

二、子传父(Emits)

子组件通过触发自定义事件,将数据传递给父组件,Vue3 + TS 可通过类型约束事件名和参数类型。

1. 子组件(Child.vue):触发事件
<template> <div> <h3>子组件</h3> <button @click="handleSendData">向父组件传值</button> <button @click="handleChangeShow">切换显示状态</button> </div> </template> <script setup lang="ts"> // 1. 定义事件类型(TS 专属) const emit = defineEmits<{ // 事件名: (参数类型) => void send-data: (msg: string, id: number) => void; change-show: (status: boolean) => void; }>(); // 2. 触发事件,传递数据 const handleSendData = () => { emit('send-data', '子组件传递的消息', 1001); }; const handleChangeShow = () => { emit('change-show', false); }; </script>
2. 父组件(Parent.vue):监听事件
<template> <div class="parent"> <h2>父组件</h2> <!-- 监听子组件的自定义事件 --> <Child @send-data="handleReceiveData" @change-show="handleChangeShow" /> <p>子组件传递的消息:{{ childMsg }}</p> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; import Child from './Child.vue'; const childMsg = ref<string>(''); // 接收子组件传递的数据 const handleReceiveData = (msg: string, id: number) => { console.log('子组件传递的ID:', id); childMsg.value = msg; }; // 处理子组件的状态变更 const handleChangeShow = (status: boolean) => { console.log('子组件切换显示状态:', status); }; </script>

三、父子双向通信(v-model)

Vue3 支持自定义v-model,实现父子组件数据双向绑定,相比 Vue2 更灵活。

1. 子组件(Child.vue):定义 v-model
<template> <div> <h3>子组件</h3> <!-- 绑定内部值,触发 update 事件 --> <input type="text" :value="modelValue" @input="emit('update:modelValue', $event.target.value)" /> <!-- 自定义名称的 v-model --> <input type="number" :value="count" @input="emit('update:count', Number($event.target.value))" /> </div> </template> <script setup lang="ts"> // 定义 v-model 对应的 Props interface Props { modelValue: string; // 默认 v-model 绑定的属性 count: number; // 自定义 v-model:count 绑定的属性 } const props = defineProps<Props>(); // 定义 update 事件(v-model 固定触发 update:xxx 事件) const emit = defineEmits<{ 'update:modelValue': (value: string) => void; 'update:count': (value: number) => void; }>(); </script>
2. 父组件(Parent.vue):使用 v-model
<template> <div class="parent"> <h2>父组件</h2> <p>默认 v-model 值:{{ inputValue }}</p> <p>自定义 v-model:count 值:{{ countValue }}</p> <!-- 使用 v-model 双向绑定 --> <Child v-model="inputValue" v-model:count="countValue" /> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; import Child from './Child.vue'; // 父组件的响应式数据 const inputValue = ref<string>('初始值'); const countValue = ref<number>(0); </script>

四、补充:父子通用通信方式(ref /provide/inject)

1. 父组件通过 ref 调用子组件方法 / 访问数据
  • 子组件(Child.vue):暴露方法 / 数据

    <script setup lang="ts"> import { ref, defineExpose } from 'vue'; const childCount = ref<number>(0); const addCount = () => { childCount.value++; }; // 显式暴露(setup 语法糖下默认私有,需 defineExpose 暴露) defineExpose({ childCount, addCount }); </script>
  • 父组件(Parent.vue):通过 ref 访

    <template> <Child ref="childRef" /> <button @click="handleCallChildMethod">调用子组件方法</button> </template> <script setup lang="ts"> import { ref } from 'vue'; import Child from './Child.vue'; // 标注子组件 ref 类型(TS 专属) const childRef = ref<InstanceType<typeof Child> | null>(null); const handleCallChildMethod = () => { if (childRef.value) { childRef.value.addCount(); // 调用子组件方法 console.log('子组件的 count:', childRef.value.childCount); // 访问子组件数据 } }; </script>
2. provide/inject(适合深层嵌套,父子也可用)
  • 父组件:提供数据

    <script setup lang="ts"> import { ref, provide } from 'vue'; import Child from './Child.vue'; const theme = ref<string>('dark'); const changeTheme = () => { theme.value = theme.value === 'dark' ? 'light' : 'dark'; }; // 提供数据(TS 可标注类型) provide('theme', theme); provide('changeTheme', changeTheme); </script>
  • 子组件:注入数据

    <script setup lang="ts"> import { inject } from 'vue'; // 注入数据并标注类型(TS 专属,设置默认值避免 null) const theme = inject<string>('theme', 'light'); const changeTheme = inject<() => void>('changeTheme', () => {}); </script>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 7:22:31

AI在企业并购估值中的应用与挑战

AI在企业并购估值中的应用与挑战 关键词:AI、企业并购估值、机器学习、数据驱动、应用挑战 摘要:本文深入探讨了AI在企业并购估值领域的应用与挑战。首先介绍了研究的背景、目的、预期读者和文档结构,明确了相关术语。接着阐述了AI与企业并购估值的核心概念及其联系,通过示…

作者头像 李华
网站建设 2026/5/1 4:48:58

《速看!提示工程架构师带你探索提示工程在新兴技术的应用奥秘》

《提示工程不是玄学&#xff1a;架构师带你拆解它在新兴技术里的实战奥秘》 备选标题 《提示工程架构师亲授&#xff1a;新兴技术中的prompt设计“底层逻辑”》《从Agent到AIGC&#xff1a;提示工程在AI新兴技术里的正确打开方式》《别再乱试prompt&#xff01;看提示工程如何…

作者头像 李华
网站建设 2026/5/1 4:44:44

开题报告 独立学院毕业生就业管理信息系统的设计与实现

目录 研究背景与意义系统目标关键技术功能模块设计创新点预期成果 项目技术支持可定制开发之功能亮点源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作 研究背景与意义 独立学院作为高等教育的重要组成部分&#xff0c;其毕业生就业管理面临…

作者头像 李华
网站建设 2026/5/1 4:45:35

MySQL复合查询详解:多表查询、子查询与合并查询

1. 基本查询回顾 1.1 复杂条件查询 -- 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时满足姓名首字母为大写J SELECT * FROM EMP WHERE (sal > 500 OR job MANAGER) AND ename LIKE J%; 1.2 排序查询 -- 按照部门号升序而雇员的工资降序排序 SELECT * FROM E…

作者头像 李华
网站建设 2026/5/1 5:48:42

​ Android 基础入门教程​3.8 Gestures(手势)

3.8 Gestures(手势) 分类 Android 基础入门教程 本节引言&#xff1a; 周六不休息&#xff0c;刚剪完了个大平头回来&#xff0c;继续码字~ 好的&#xff0c;本节给大家带来点的是第三章的最后一节——Gestures(手势)&#xff0c; 用过魅族手机的朋友相信对手势肯定是不陌生…

作者头像 李华