最近正在将一个使用单文件组件的 Options API 的 Vue2 JavaScript 项目升级为 Vue3 typescript,并利用 Composition API 的优势。

  比如,下面这种 选项API 方式:

export default {
props: {
name: {
type: String,
required: true.
}
},
emits: ['someEvent', 'increaseBy']
};
我们将它转成 组合API 方式:
const props = defineProps<{
name: string;
}>();
const emit = defineEmits<{
(event: 'someEvent): void;
(event: 'increaseBy', value: number): void;
}>();

从 选项API 的 emit 和 props 到 组合API 的 defineemit 和 defineProps 函数的基于类型语法的转换并不简单。我也很好奇 Vue 是如何处理接口的。

TypeScript 接口是只在设计和编译时存在的结构。它们在JavaScript运行时之前被过滤掉,那么它们是如何影响组件的行为的呢?

我想知道是否有办法看到Vue如何解释传递给 defineEmits 和 defineProps 的通用参数。如果你注意到文档中说你不需要导入 defineEmits 和 defineProps 函数。这是因为它们实际上是同名的JavaScript函数的宏。在进行完整的 TypeScript 传递之前,Vue webpack插件使用TypeScript的 AST(抽象语法树)来推导JavaScript版本的函数选项。

如果不是因为宏:

 defineProps<{
    prop1: string;
    prop2: number;
  }>();

就会变成:

 defineProps();

这样就会导致参数缺失的错误。

如果看一下Vue的 SFC(单文件组件)编译器源代码,有一个叫做 compileScript 的函数。我开始尝试用最少的参数来调用这个函数,这样就不会出错,并模拟任何不重要的必要参数。最终发现了另一个叫 parse 的函数。这给了我所需的大部分参数,只剩下要mock的组件 id

这里有一个小脚本,它接收SFC的 .vue文件并输出 Vue 如何解释 TypeScript。

import { readFile, writeFile } from "fs";
import parseArgs from "minimist";
import { parse, compileScript } from "@vue/compiler-sfc";
const { file, out } = parseArgs(process.argv.slice(2), {
string: ["file", "out"],
alias: {
file: "f",
out: "o"
}
});
const filename = file;
const mockId = "xxxxxxxx";
readFile(filename, "utf8", (err, data) => {
const { descriptor } = parse(data, {
filename
});
const { content } = compileScript(descriptor, {
inlineTemplate: true,
templateOptions: {
filename
},
id: mockId
});
if (out) {
writeFile(out, "utf8", content);
} else {
process.stdout.write(content);
}
});
 

事例地址:https://stackblitz.com/edit/node-fzuykn?file=index.js

例如,有如以下组件:

interface Bar {
prop1: string;
prop2: number;
} defineProps<{
bar: Bar;
bars: Bar[];
asdf1?: boolean;
asdf2: string[];
}>();

输出:
interface Bar {
prop1: string;
prop2: number;
} export default /*#__PURE__*/_defineComponent({
__name: 'demo',
props: {
bar: { type: Object, required: true },
bars: { type: Array, required: true },
asdf1: { type: Boolean, required: false },
asdf2: { type: Array, required: true }
},
setup(__props: any) {
return (_ctx: any,_cache: any) => {
return (_openBlock(), _createElementBlock("div"))
}
}


正如上面所看到的,SFC编译器采用TypeScript类型信息,并建立了 props 对象。原始类型是一对一的。接口变成对象,而 ? 可选语法驱动 required 的属性。

Vue3中defineEmits、defineProps 是怎么做到不用引入就能直接用的的更多相关文章

  1. Dynamics CRM 365 不用按钮工具,直接用js脚本控制按钮的显示隐藏

    Dynamics CRM 365 不用按钮工具,直接用js脚本控制按钮的显示隐藏: try { // 转备案按钮 let transferSpecialRequestButton = parent.p ...

  2. vue3中的defineProps,watch,computed

    在vue3的setup语法糖中,defineProps不需要引入了 <script setup> import { computed } from '@vue/reactivity'; i ...

  3. 【ask】vmware(NAT)中的linux突然无法访问互联网网址,但是直接用ip可以访问。

    前两天虚拟机里的linuxmint不知何故,突然无法访问互联网了.依稀记得是升级了win7下面的360安全卫士之后发生的事情.所以, 第1步就开始去找防火墙的各种设置,结果没有查到结果. 第2步猛然看 ...

  4. 端午总结Vue3中computed和watch的使用

    1使用计算属性 computed 实现按钮是否禁用 我们在有些业务场景的时候,需要将按钮禁用. 这个时候,我们需要使用(disabled)属性来实现. disabled的值是true表示禁用.fals ...

  5. Module Federation 模块联邦 在Vue3中使用Vue2搭建的微服务

    前言: 备注:本文基于对webpack Module Federation有一定了解的情况下 一般情况下使用模块联邦都是会使用相同的版本,如Vue2的组件时在Vue2中使用,但我为什么会在Vue3项目 ...

  6. vue3中pinia的使用总结

    pinia的简介和优势: Pinia是Vue生态里Vuex的代替者,一个全新Vue的状态管理库.在Vue3成为正式版以后,尤雨溪强势推荐的项目就是Pinia.那先来看看Pinia比Vuex好的地方,也 ...

  7. pig的grunt中shell命令不稳定,能不用尽量不用

    shell命令:mv a b   将文件a改名为b, 可如果b已经存在,比如/test文件下有a和b两个文件,执行mv a b后,b被覆盖的了.也就是/test文件下只有a. 但是mv命令在pig的g ...

  8. 在Javascript中 声明时用"var"与不用"var"的区别,== 和 ===的区别

    今天,被问到两个JS问题,当时没回答到重点,问题虽然看起来简单,但是细节却马虎不得,在此做下记录: 1. 在Javascript中 声明时用"var"与不用"var&qu ...

  9. vue3中使用axios如何去请求数据

    在vue2中一般放在created中,但是在vue3中取消了created生命周期,请求方式有两种 直接在setup中去获取数据 setup(props) { const data = reactiv ...

随机推荐

  1. neo4j中重复节点问题

    neo4j中重复节点问题 neo4j中,在导入csv文件时,可能会出现有重复节点的现象.可以分为以下步骤解决:1.先查看下某个标签下的节点总数match (n:PERSON) return count ...

  2. windiws下安装Composer

    1.先下载Composer-Setup.exe,下载地址:下载Composer .会自动搜索php.exe的安装路径,如果没有,就手动找到php路径下的php.exe. 2.在PHP目录下,打开php ...

  3. 龙芯发布 .NET 6 SDK 6.0.105-ea1 LoongArch64 版本

    龙芯平台.NET,是龙芯公司基于开源社区.NET独立研发适配的龙芯版本,我们会长期进行安全更新和错误修复,并持续进行性能优化.社区.NET7版本开始已经原生支持LoongArch64架构源码.具备如下 ...

  4. 『忘了再学』Shell流程控制 — 36、for循环介绍

    目录 1.for循环介绍 2.示例 语法一举例: 语法二举例: 3.for循环总结 4.练习:批量解压缩脚本 方式一:批量解压缩 方式二:批量解压缩 1.for循环介绍 for循环是固定循环,也就是在 ...

  5. Java基础-JVM篇

    1.1 .线程 ​ 这里所说的线程指程序执行过程中的一个线程实体.JVM 允许一个应用并发执行多个线程.Hotspot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系.当线程本地存储. ...

  6. 几种常见的DoS攻击

    DoS为Denial of Service的简称,意思是拒绝服务.DoS攻击是一种使被攻击者无法正常提供服务的攻击.常见的攻击方式有以下几种类型:   LAND Local Area Network ...

  7. go int64传到前端导致溢出问题排查

    简介 ​ 开周会的时候一位同事分享了一个踩坑经验,说在go里面还好好的int64类型,到前端就变得奇奇怪怪了,和原来不一样了.正好我对前端javascript有一点点了解,然后连夜写了点代码探索了一下 ...

  8. RPA应用场景-报税机器人

    场景概述 报税机器人 所涉系统名称 税务网站 人工操作(时间/次) 53分钟 所涉人工数量 60 操作频率 每月 场景流程 1.通过RPA自动将财税信息从对应系统中导出 2.RPA根据不同的税务报表规 ...

  9. 使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

    环境:Core:3.1的项目 说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失, 对数据有要求的该方案不适用,不能照搬需要持久化处理, 另外发布到Linux Docker中通常不会自 ...

  10. bat-安装程序-切换路径的问题(小坑)

    当批处理以管理员身份运行时,默认的cmd路径是 C:\Windows\system32 如果在批处理所在目录下存放了一些 安装程序,使用bat安装程序时,bat中去执行时 不会去当前目录去找 exe文 ...