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

前言:

最近正在将一个使用单文件组件的 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 不用引入便直接用的文章就介绍到这了,更多相关Vue3 defineEmit 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue3 setup语法糖之组件传参(defineProps、defineEmits、defineExpose)示例详解

    vue3官方文档 defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏.他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉. defineProps 接收与 props 选项相同的值,defineEmits 接收与 emits 选项相同的值. 父传子  - defineProps 父组件 <template> <div class="Father"> &

  • Vue3中props和emit的使用方法详解

    目录 作用:父组件通过 props 向下传递数据给子组件: 用法1(不指定类型的简单接受): 用法2(接受同时进行类型限制): 用法3(接受同时类型限制+默认值指定): 注意: emit的使用 总结 作用:父组件通过 props 向下传递数据给子组件: 用途:当有一种类型的组件需要被使用多次,每一次的调用都只是特定的地方不同,就好像一张个人简介表,每次填的人的信息都不同,但是结构都是一样的. 用法1(不指定类型的简单接受): 在父组件里面引入子组件,通过子组件的标签属性传递参数,在子组件里面定义

  • vue3中使用ref和emit来减少props的使用示例详解

    目录 前言 示例 示例1 示例2 前言 在之前开发vue2项目中,props 属性在组件中经常使用来进行组件通信.现在在开发vue3项目的过程中,我们开发小组渐渐的减少props的使用,转而用ref 和 emit 来代替.缺点不太清楚,但是好处还是挺多的.下面结合实际的开发常见来举例. 示例 示例1 以弹窗组件来说,之前vue2时是通过props属性来控制弹窗的打开,比如下面这个新增弹窗退货的弹窗组件(大多数清空下,新增和修改一般是一个组件) <add-return-goods :visible

  • 一文详细聊聊vue3的defineProps、defineEmits和defineExpose

    目录 defineProps defineEmits defineExpose 总结 最近在开发中用到了vue3的defineProps.defineEmits和defineExpose,感觉发现新大陆一般,所以利用闲碎时间对这三个方法做个总结. defineProps const props = defineProps<{ foo: String, bar?: Number }>() defineProps 是vue3的写法并且是一个仅 <script setup> 中可用的编译

  • vue3.0语法糖内的defineProps及defineEmits解析

    目录 语法糖内的defineProps及defineEmits 1.defineProps 2.defineEmits vue语法糖的说明 语法糖内的defineProps及defineEmits 1.defineProps 获取组件传值 <div :style="fontstyle"> <div class="rate" @mouseout="mouseOut"> <span @mouseover="mo

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

    前言: 最近正在将一个使用单文件组件的 Options API 的 Vue2 JavaScript 项目升级为 Vue3 typescript,并利用 Composition API 的优势. 比如,下面这种 选项API 方式: export default { props: { name: { type: String, required: true. } }, emits: ['someEvent', 'increaseBy'] }; 我们将它转成 组合API 方式: const props

  • vue3中defineProps传值使用ref响应式失效详解

    子组件接收父组件的传参. 父组件: <template> <Son :data="data"/> </template> <script setup> import { ref } from "vue"; let data = ref('hello') setTimeout(() => { data.value = 'how are you doing' }, 2000) </script> 子组件:

  • element-plus 在vue3 中不生效的原因解决方法(element-plus引入)

    目录 1.安装element-plus (3种方式 ) 2. 在main.js种引用 原因一 原因二 vue3.0 不兼容 element-ui ,于是推出了element-plus 1.安装element-plus (3种方式 ) npm install element-plus --save (推荐)yarn add element-pluspnpm install element-plus 2. 在main.js种引用 import 'element-plus/theme-chalk/in

  • Vue3中10多种组件通讯方法小结

    目录 Props emits expose / ref Non-Props 单个根元素的情况 多个元素的情况 v-model 单值的情况 多个 v-model 绑定 v-model 修饰符 插槽 slot 默认插槽 具名插槽 作用域插槽 provide / inject 总线 bus getCurrentInstance Vuex State Getter Mutation Action Module Pinia 安装 注册 mitt.js 安装 使用 本文讲解 Vue 3.2 组件多种通讯方式

  • vue3中emit('update:modelValue')使用简单示例

    父 <template> <TestCom v-model="test1" v-model:test2="test2"></TestCom> <h1>{{test1}}测试1</h1> <h1>{{test2}}测试2</h1> </template> <script setup> import { ref, reactive } from 'vue' con

  • vue3中setup-script的应用实例

    目录 新特性的产生背景 内部变量 子父级传值 总结 新特性的产生背景 在了解它怎么用之前,可以先了解一下它被推出的一些背景,可以帮助你对比开发体验上的异同点,以及了解为什么会有这一章节里面的新东西. 在 Vue 3.0 的 .vue 组件里,遵循 SFC 规范要求(注:SFC,即 Single-File Component,.vue 单组件),标准的 setup 用法是,在 setup 里面定义的数据如果需要在 template 使用,都需要 return 出来. 如果你使用的是 TypeScr

  • vue3中element-plus icon图标的正确使用姿势

    目录 前言: 改变: 错误使用: 正确使用: setup script扩展 更新 总结 前言: 为了适应vue3的更新,element组件也将其内容升级为了plus用以配套的使用,很多组件新增了更加多元的功能,但我用的时候就觉得那个icon图标,怎么变得特别难用呢?原来是没有掌握正确的使用方法 改变: // 原来 <i class="el-icon-edit"></i> // plus <el-icon :size="size" :co

  • Vue3 中 watch 与 watchEffect 区别及用法小结

    目录 响应式依赖收集 Watch WatchEffect 什么时候用什么? 大部分时候用 watch 显式的指定依赖以避免不必要的重复触发,也避免在后续代码修改或重构时不小心引入新的依赖.watchEffect 适用于一些逻辑相对简单,依赖源和逻辑强相关的场景. 你可以认为他们是同一个功能的两种不同形态,底层的实现是一样的. watch- 显式指定依赖源,依赖源更新时执行回调函数 watchEffect - 自动收集依赖源,依赖源更新时重新执行自身 响应式依赖收集 首先先需要了解一下 vue 3

  • vue3中实现音频播放器APlayer的方法

    目录 前言: 官方: 实现步骤: 前言: vue2的时候,分享了一个很好用的插件是vue-aplayer,但是他是不支持vue3的,这里分享vue3使用APlayer来实现一个播放器的方法. 实现效果: 官方: git地址:点我 api地址:点我 实现步骤: 1.安装 npm: npm install aplayer --save Yarn: yarn add aplayer 2.页面中引入 import APlayer from 'APlayer'; import 'APlayer/dist/

  • Vue3中slot插槽基本使用

    目录 1.插槽基本使用 2.插槽默认内容 3.具名插槽 3.1 基本使用 3.2 简写 3.3 默认插槽与具名插槽混用 4.动态插槽名 5.插槽作用域问题 6.作用域插槽 6.1 默认插槽作用域传值 6.2 具名插槽作用域传值 总结 使用Vue的小伙伴相信你一定使用过插槽,如果你没有用过,那说明你的项目可能不是特别复杂.插槽(slot)可以说在一个Vue项目里面处处都有它的身影,比如我们使用一些UI组件库的时候,我们通常可以使用插槽来自定义我们的内容. 1.插槽基本使用 插槽的用途就和它的名字一

随机推荐