当前位置: 首页 > news >正文

Vue3实战笔记(33)—组件传值props终章

文章目录

  • 前言
  • 一、运行时声明、基于类型的声明
  • 二、一个小小的好奇心
  • 三、非 script setup场景下
  • 总结


前言

在 Vue 3 中,组件的声明方式主要有两种:运行时声明和基于类型的声明。这两种方式在 Vue 3 的 Composition API 中体现得尤为明显。


一、运行时声明、基于类型的声明

这两天一直有一个疑问,为什么这种方式声明属性不能支持Type和interface?

//这种方式会报错,同理,Type声明的类型也不能defineProps({navigationItem :NavigationItem,//“NavigationItem”仅表示类型,但在此处却作为值使用。ts(2693)author: Person,book:shtype//“shtype”仅表示类型,但在此处却作为值使用。ts(2693})

先来了解一下两个概念:运行时声明、基于类型的声明

当使用


<script setup lang="ts">
const props = defineProps({foo: { type: String, required: true },bar: Number
})props.foo // string
props.bar // number | undefined
</script>

这被称之为“运行时声明”,因为传递给 defineProps() 的参数会作为运行时的 props 选项使用。

然而,通过泛型参数来定义 props 的类型通常更直接:


<script setup lang="ts">
const props = defineProps<{foo: stringbar?: number
}>()
</script>

这被称之为“基于类型的声明”。编译器会尽可能地尝试根据类型参数推导出等价的运行时选项。在这种场景下,我们第二个例子中编译出的运行时选项和第一个是完全一致的。

基于类型的声明或者运行时声明可以择一使用,但是不能同时使用。

我们也可以将 props 的类型移入一个单独的接口中:


<script setup lang="ts">
interface Props {foo: stringbar?: number
}const props = defineProps<Props>()
</script>

还可以从外部导入接口声明:


<script setup lang="ts">
import type { Props } from './foo'const props = defineProps<Props>()
</script>

在 3.2 及以下版本中,defineProps() 的泛型类型参数仅限于类型文字或对本地接口的引用。

这个限制在 3.3 中得到了解决。最新版本的 Vue 支持在类型参数位置引用导入和有限的复杂类型。但是,由于类型到运行时转换仍然基于 AST,一些需要实际类型分析的复杂类型,例如条件类型,还未支持。您可以使用条件类型来指定单个 prop 的类型,但不能用于整个 props 对象的类型。
上一篇文章中注意到Prop校验的话,有一个默认值选项,官方文档说,

当使用基于类型的声明时,我们失去了为 props 声明默认值的能力。这可以通过 withDefaults 编译器宏解决:


export interface Props {msg?: stringlabels?: string[]
}const props = withDefaults(defineProps<Props>(), {msg: 'hello',labels: () => ['one', 'two']
})

这将被编译为等效的运行时 props default 选项。此外,withDefaults 帮助程序为默认值提供类型检查,并确保返回的 props 类型删除了已声明默认值的属性的可选标志。

二、一个小小的好奇心

能不能在接口中声明默认值?搜了一下:
在这里插入图片描述
特别好奇,尝试了一下:

interface NavigationItem{children: Array<NavigationItem>,id:string,name:string = 'sh',propDef: {type: String,required: false,default:""},path:string,child:{id:string,name:string,path:string,child:{}}}

在这里插入图片描述
接口中也不应该这样的写法,但是编译器没有报错:

propDef: {type: String,required: false,default:""}

实例化时候:

在这里插入图片描述
这是类型啊!!!所以不要把接口和对象的各种约束等方式混淆了。老老实实按照官方文档来吧,好奇害死猫,浪费了不少时间去验证一些奇奇怪怪的想法。还有就是搜到的不一定是你需要的。

三、非 script setup场景下

如果没有使用 script setup,那么为了开启 props 的类型推导,必须使用 defineComponent()。传入 setup() 的 props 对象类型是从 props 选项中推导而来:


import { defineComponent } from 'vue'export default defineComponent({props: {message: String},setup(props) {props.message // <-- 类型:string}
})

重点来了,基于类型的声明能干的事儿,运行时声明也能干
通过基于类型的声明,一个 prop 可以像使用其他任何类型一样使用一个复杂类型:


<script setup lang="ts">
interface Book {title: stringauthor: stringyear: number
}const props = defineProps<{book: Book
}>()
</script>

对于运行时声明,我们可以使用 PropType 工具类型:


import type { PropType } from 'vue'const props = defineProps({book: Object as PropType<Book>
})

其工作方式与直接指定 props 选项基本相同:


import { defineComponent } from 'vue'
import type { PropType } from 'vue'export default defineComponent({props: {book: Object as PropType<Book>}
})

总结

运行时声明: 这是一种传统的 Vue 组件声明方式,它主要依赖于 Vue 的运行时特性。在 Vue 2.x 中,这种方式主要通过 options API 实现,例如 data、methods、computed、watch 等。在 Vue 3 中,虽然 Composition API 被引入,但运行时声明仍然是一种可选的方式。例如,可以直接在 setup 函数中定义响应式变量、方法等,无需额外的类型注解,Vue 3 的响应式系统会在运行时自动处理这些声明。
基于类型的声明: 这种方式是 Vue 3 新引入的,特别是与 TypeScript 一起使用时,可以提供更严格的类型检查和更好的开发体验。基于类型的声明通常涉及到使用 TypeScript 的类型注解来定义组件的 props、emits、slots 以及其他响应式状态。Vue 3 的 Composition API,如 ref、reactive、computed、watch 等函数,都可以与 TypeScript 的类型系统很好地配合工作。

人间的事往往如此,当时提起痛不欲生,几年之后,也不过是一场回忆而已。

相关文章:

  • jsp连接数据库
  • 【考研数学】李林《880》是什么难度水平强化够用吗
  • 全文检索ElasticSearch简介
  • ubuntu 卸载 程序
  • 云和恩墨海外首秀在吉隆坡召开的2024中国智能科技与文化展览会
  • 操作系统 c语言简单模仿进程创建和时间片轮转调度算法中的进程调度
  • 使用决策树对金融贷款数据进行分析
  • docker swarm多主机之间的端口无法访问,但能ping通 问题排查及解决
  • SQL常用基础语句(一)-- FGHIJ开头
  • 【C++初阶】--- C++入门(上)
  • 开源大模型与闭源大模型:技术哲学的较量
  • 微服务远程调用 RestTemplate
  • 【MySQL精通之路】SQL优化(1)-查询优化(8)-嵌套联接优化
  • 在docker中安装官方rocketmq
  • 【C语言回顾】联合和枚举
  • 【Leetcode】101. 对称二叉树
  • 【Amaple教程】5. 插件
  • 10个最佳ES6特性 ES7与ES8的特性
  • CSS实用技巧干货
  • javascript从右向左截取指定位数字符的3种方法
  • PHP的Ev教程三(Periodic watcher)
  • Python利用正则抓取网页内容保存到本地
  • ReactNative开发常用的三方模块
  • Sublime text 3 3103 注册码
  • tweak 支持第三方库
  • unity如何实现一个固定宽度的orthagraphic相机
  • 大快搜索数据爬虫技术实例安装教学篇
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 每天一个设计模式之命令模式
  • 批量截取pdf文件
  • 前端_面试
  • 日剧·日综资源集合(建议收藏)
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 阿里云重庆大学大数据训练营落地分享
  • ​​​【收录 Hello 算法】10.4 哈希优化策略
  • #if和#ifdef区别
  • $.ajax()
  • (9)STL算法之逆转旋转
  • (C语言)球球大作战
  • (Python) SOAP Web Service (HTTP POST)
  • (windows2012共享文件夹和防火墙设置
  • (独孤九剑)--文件系统
  • (附源码)php新闻发布平台 毕业设计 141646
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (三)终结任务
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (译)2019年前端性能优化清单 — 下篇
  • (原)Matlab的svmtrain和svmclassify
  • (正则)提取页面里的img标签
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .java 9 找不到符号_java找不到符号
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 材料检测系统崩溃分析