Vue3中defineEmits、defineProps 不用引入便直接用

作者:码农小宋??????? 时间:2024-05-09 09:53:01 

前言:

最近正在将一个使用单文件组件的 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?? 的属性。

来源:https://blog.51cto.com/u_15430445/5691053

标签:Vue3,defineEmits,defineProps
0
投稿

猜你喜欢

  • Python jieba库用法及实例解析

    2021-04-15 22:11:44
  • python修改全局变量可以不加global吗?

    2021-01-11 08:10:56
  • Django使用原生SQL查询数据库详解

    2024-01-21 00:58:08
  • pycharm修改file type方式

    2022-10-08 15:25:36
  • django富文本编辑器的实现示例

    2021-02-02 06:20:33
  • TensorFlow绘制loss/accuracy曲线的实例

    2022-01-25 08:01:16
  • Python中pymysql 模块的使用详解

    2024-01-16 21:07:25
  • 如何判断JavaScript变量的类型

    2009-02-25 12:28:00
  • Python中如何添加自定义模块

    2023-06-09 23:24:38
  • Python的numpy库中将矩阵转换为列表等函数的方法

    2021-06-19 12:18:21
  • Python socket实现简单聊天室

    2022-06-20 02:13:27
  • 如何修改被表单引用的ASP页面?

    2010-06-10 18:32:00
  • 使用Pycharm(Python工具)新建项目及创建Python文件的教程

    2022-06-07 11:43:52
  • opencv-python+yolov3实现目标检测

    2022-01-18 06:45:17
  • python计算列表元素与乘积详情

    2023-05-12 00:50:19
  • Python使用pycharm导入pymysql教程

    2024-01-17 22:47:49
  • 使用PyInstaller库把Python程序打包成exe

    2023-11-27 17:40:28
  • 使用Mybatis对数据库进行单表操作的实现示例

    2024-01-16 13:50:45
  • Python常用知识点汇总

    2023-02-17 09:42:44
  • Python中shape[0]、shape[1]和shape[-1]分别的意思详解(附代码)

    2021-01-23 05:57:20
  • asp之家 网络编程 m.aspxhome.com