您现在的位置是:亿华云 > 人工智能

Vue3中DefineEmits、DefineProps 是怎么做到不用引入就能直接使用

亿华云2025-10-02 19:12:18【人工智能】7人已围观

简介最近正在将一个使用单文件组件的 Options API 的 Vue2 JavaScript 项目升级为 Vue3 typescript,并利用 Composition API 的优势。比如,下面这种选

最近正在将一个使用单文件组件的不用 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 的通用参数。云南idc服务商如果你注意到文档中说你不需要导入 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 的属性。

很赞哦!(4)