【2024】作为前端开发,必须掌握的 Vue3 的 5 个组合式 API 方法

news2025/1/16 17:50:52

引言:2024 你还不知道 Vue3 的 definePropsdefineEmitsdefineExposedefineOptionsdefineSlots 吗?这几个 Vue3 组合式 API 方法不仅开发常用(涉及组件通信、组件复用等),在面试中也是不可或缺的一部分!

掌握这些方法将有助于我们更深入地理解和运用 Vue 3 的组合式 API,这篇文章做了详细的技术点总结(直接复制使用即可)和经验分享,如果你也有好的分享,欢迎评论区一起讨论。

前言

在 Vue3 中,defineProps、defineEmits、defineExpose、defineOptions、defineSlots是一组新的功能函数,用于定义组件的属性、事件、暴露、选项和插槽。

函数名称用途基本用法备注
defineProps定义组件的属性(props)const props = defineProps({...});提供了基本的属性和事件处理通信功能
defineEmits定义组件可以发出的事件const emit = defineEmits([...]);同上
defineExpose定义组件暴露给父组件的方法或属性defineExpose({...});提供了更高级的组件封装能力,适合需要高度自定义和复用的组件。
defineOptions在组合式 API 中设置组件的选项defineOptions({...});提供了在组合式 API 中设置组件选项的能力,适用于复杂组件或者需要大量配置的场景。
defineSlots定义和访问组件的插槽内容const slots = defineSlots();简化了插槽内容的处理,适合需要动态内容和复杂布局的组件。

以下详细列举了如何在开发中使用这些新的功能函数,并分享了一些扩展。如果有任何问题,请随时告知,我会及时帮助指正。

使用示例与分析

1. defineProps:定义组件属性

在 Vue 3 中,通过 defineProps 函数可以声明和验证组件的属性,使得父子组件之间数据的传递更加安全和可控。

适用于需要明确定义和验证输入属性的组件,特别是在使用 TypeScript 等类型系统时,能够提供良好的类型推断和验证。简化了属性定义和验证流程,但是对于简单的属性传递,可能显得有些繁琐,特别是在不需要严格验证的情况下。

例如,假设我们有一个简单的计数器组件,它接收一个初始计数值作为属性:

<!-- Counter.vue -->
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 定义属性
const props = defineProps({
  initialCount: {
    type: Number,
    required: true
  }
});

// 使用属性
const count = ref(props.initialCount);

function increment() {
  count.value++;
}
</script>

父组件

<!-- Parent.vue -->
<template>
  <div>
    <Counter :initialCount="count" />
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import Counter from './Counter.vue';

const count = ref<number>(100);
</script>

2. defineEmits:定义组件事件

defineEmits 允许组件明确声明它可以触发的事件,提供了一种类型安全的事件处理机制,替代了传统的 $emit 方法。

适用于需要明确定义和管理组件事件的场景,尤其是在复杂的组件通信和状态管理中尤为有用。例如,我们可以扩展我们的计数器组件,使其在计数值变化时发出事件,被父组件接收到。

<!-- Counter.vue -->
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="handleIncrement">Increment</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 定义属性
const props = defineProps({
  initialCount: {
    type: Number,
    required: true
  }
});

// 定义事件
const emit = defineEmits(['update:count']);

const count = ref(props.initialCount);

function handleIncrement() {
  count.value++;
  emit('update:count', count.value);
}
</script>

父组件

<!-- Parent.vue -->
<template>
  <div>
    <Counter :initialCount="count" @update:count="handleCountUpdate" />
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import Counter './Counter.vue'

const count = ref<number>(100)

function handleCountUpdate(value: number) {
  console.log(value)
}
</script>

defineProps(定义组件属性)与defineEmits(定义组件事件)这两个组合式 API,是我们在 Vue3 组件通信常用的方法之一。

3. defineExpose:暴露给父组件的方法或属性

defineExpose 函数允许组件开发者明确定义哪些内部方法或属性可以被父组件访问和调用,增强了组件的封装性和复用性。

适用于需要向外部暴露特定方法或属性的组件,使得父子组件之间的通信更加直接和有效。提高了组件的封装性和可复用性,但是可能会暴露过多的内部实现细节,所以使用时需要注意暴露方法。

我们继续修改我们的计数器组件,使其暴露一个重置计数值的方法:

<!-- Counter.vue -->
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// 定义属性
const props = defineProps({
  initialCount: {
    type: Number,
    required: true
  }
});

// 定义事件
const emit = defineEmits(['update:count']);

const count = ref(props.initialCount);

function increment() {
  count.value++;
  emit('update:count', count.value);
}

function resetCount() {
  count.value = props.initialCount;
}

// 暴露方法
defineExpose({
  reset: resetCount
});
</script>

现在,父组件可以通过引用调用子组件的 reset 方法:

<!-- Parent -->
<template>
  <Counter ref="counter" :initialCount="10" @update:count="handleCountUpdate" />
  <button @click="resetCounter">Reset Counter</button>
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import Counter from './Counter.vue';

const counter = ref(null);

function handleCountUpdate(value) {
  console.log(value);
}

function resetCounter() {
  counter.value.reset();
}
</script>

请注意:defineExpose[…] 定义的方法或者属性,由父组件来使用。但是,必须配合在父组件设置 ref 来使用。

4. defineOptions:设置组件选项

defineOptions 函数允许在组合式 API 中设置组件的选项,如 namecomponentsdirectives,使得在组合式 API 中使用类似于选项式 API 的配置。

适用于需要在组合式 API 中使用选项式 API 的配置方式的场景,尤其是对于复杂组件的配置和管理非常有帮助。提供了类似于选项式 API 的配置方式,增强了组件的配置灵活性和可扩展性。但是对于简单的组件可能显得过于复杂,不适合所有场景。

defineOptions({
  name: 'ComponentName',
  components: { ... },
  directives: { ... }
});

下面,我们来定义一个包含子组件和自定义指令的组件:

<!-- ParentComponent.vue -->
<template>
  <div v-focus>
    <p>{{ message }}</p>
    <ChildComponent />
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';

const message = ref('Hello from ParentComponent');

// 定义选项
defineOptions({
  name: 'ParentComponent',
  components: {
    ChildComponent
  },
  directives: {
    focus: {
      mounted(el) {
        el.focus();
      }
    }
  }
});
</script>

5. defineSlots:处理组件插槽

defineSlots 函数用于定义和访问组件的插槽内容,简化了在组合式 API 中处理动态内容和复杂布局的逻辑。

适用于需要动态内容和复杂布局的组件,能够提升组件的灵活性和可重用性。简化了插槽内容的处理逻辑,但目前在实际应用中用到的场景相对较少,对于简单的插槽处理可能显得过于复杂。

这里有一个例子,展示了如何在子组件中根据不同的插槽名和默认插槽,访问和处理多个插槽内容:

<!-- SlotComponent.vue -->
<template>
  <div>
    <div class="header">
      <slot name="header"></slot>
    </div>
    <div class="content">
      <slot></slot>
    </div>
    <div class="footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script setup>
import { defineSlots } from 'vue';

const slots = defineSlots();
console.log('Header Slot content:', slots.header ? slots.header() : 'No header content');
console.log('Default Slot content:', slots.default ? slots.default() : 'No default content');
console.log('Footer Slot content:', slots.footer ? slots.footer() : 'No footer content');
</script>

在父组件中使用插槽:

<!-- ParentComponent.vue -->
<template>
  <div>
    <SlotComponent>
      <template #header>
        <h2>Header Slot</h2>
      </template>
      <template #footer>
        <p>Footer Slot</p>
      </template>
    </SlotComponent>
  </div>
</template>

<script setup>
import SlotComponent from './SlotComponent.vue';
</script>

适用场景总结

definePropsdefineEmits:这两者多配合使用,适用于简单组件和快速开发,因为它们提供了基本的属性和事件处理功能。

defineExpose:适用于高度封装和复用性要求,它提供了更高级的组件封装能力,可以将子组件的能力暴露出去给父组件。

defineOptions:适用于复杂组件和高级配置,它提供了在组合式 API 中设置组件选项的能力,适用于复杂组件或者需要大量配置的场景。

defineSlots 适用于插槽处理和动态内容,它简化了对于插槽内容的处理。

扩展

1. vue3 与 ESLint

在使用 Vue 3 和 ESLint 时,可能需要配置 ESLint 以识别 Vue 3 的组合式 API 函数。这可以通过在 ESLint 配置文件中添加全局变量声明来实现。以下是一个示例配置:

// .eslintrc.js
module.exports = {
  root: true,
  env: {
    node: true,
    browser: true,
    es2021: true
  },
  parser: 'vue-eslint-parser',
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-strongly-recommended'
    // 'standard'
  ],
  parserOptions: {
    ecmaVersion: 12,
    parser: '@typescript-eslint/parser',
    sourceType: 'module'
  },
  plugins: [
    'vue',
    '@typescript-eslint'
  ],
  rules: {
    quotes: [1, 'single'],
    'vue/script-setup-uses-vars': 0,
    'vue/no-multiple-template-root': 'off',
    'no-unused-vars': 0,
    camelcase: 0,
    'no-undef': 0,
    'vue/max-attributes-per-line': ['error', {
      singleline: {
        max: 3
      },
      multiline: {
        max: 3
      }
    }]
  },
  globals: {
    withDefaults: true,
    defineExpose: true,
    defineEmits: true,
    defineProps: true
  }
}

这种配置告诉 ESLint 这些函数是全局的,并且是只读的(即不能重新赋值)。这将防止 ESLint 报告未定义的全局变量错误。

2. withDefaults辅助函数(很重要)

建议在代码中,一定要配置 withDefaults

withDefaults 是一个辅助函数,可以帮助在定义组件属性时设置默认值,使得组件属性在没有传递值时有一个预设的默认值。这样可以简化代码,避免在每个属性上都手动设置默认值。

而且由于 withDefaults 可以帮助定义属性的类型和默认值,使得 TypeScript 能够正确地推断和检查组件的属性使用。

const props = withDefaults(defineProps({
  message: String,
  count: { type: Number, default: 0 },
}));

或者

const props = withDefaults(defineProps<{
  message: string,
  count: number,
}>(), {
  message: 'hello',
  count: 0
})

结论

Vue 3 的组合式 API 为开发者提供了更多的灵活性和模块化能力。通过使用 definePropsdefineEmitsdefineExposedefineOptionsdefineSlots,我们可以更加简洁和直观地定义和使用组件的属性、事件、暴露方法、选项和插槽。

希望本文能帮助你深入理解 Vue 3 的组合式 API 函数。在评论区分享你的见解或提出问题,让我们一起探讨和学习!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2198872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot实现电子文件签字+合同系统!

一、前言 二、项目源码及部署 1、项目结构及使用框架 2、项目下载及部署 三、功能展示 一、前言 今天公司领导提出一个功能,说实现一个文件的签字+盖章功能,然后自己进行了简单的学习,对文档进行数字签名与签署纸质文档的原因大致相同,数字签名通过使用计算机加密来验证 (…

LabVIEW提高开发效率技巧----阻塞时钟

在LabVIEW开发中&#xff0c;阻塞时钟&#xff08;Blocking Timed Loops&#xff09;是一种常见且强大的技术&#xff0c;尤其适用于时间关键的应用。在这些应用中&#xff0c;精确控制循环的执行频率是关键任务。阻塞时钟通过等待循环的执行完成后再进入下一次迭代&#xff0c…

鸿蒙 Next 实战: 烟花模拟器

前言 通过上一篇文章可以看出&#xff0c;要在鸿蒙应用中实现特别炫的特效还是比较复杂。动画固然重要&#xff0c;但如果在赶工期的情况下&#xff0c;大家都会优先业务&#xff0c;那有没有简单快速的方法呢&#xff1f; 有的&#xff0c;也用像 Android 和 iOS 里 WebView …

.Net Core 接口或网站发布到IIS

将.Net Core 接口或网站发布到IIS上&#xff0c;需要遵循一系列步骤来确保正确配置和部署。下面将以.NET Core 3.1的api接口发布示范&#xff1a; 一、环境准备 安装.NET Core 3.1 SDK和运行时&#xff1a; 在服务器上安装.NET Core 3.1 SDK&#xff08;如果需要在服务器上编译…

宝兰德亮相2024国际信息通信展:数智创新,信创力量!

9月25日-27日&#xff0c;2024中国国际信息通信展览会在北京国家会议中心隆重召开。本届展会以“推动数实深度融合&#xff0c;共筑新质生产力”为主题&#xff0c;全面展示信息通信业发展最新成果。作为国内领先的基础软件供应商&#xff0c;宝兰德再度闪耀会场&#xff0c;在…

[ROS】rqt工具箱

作用&#xff1a; 可以方便的实现 ROS 可视化调试&#xff0c;并且在同一窗口中打开多个部件&#xff0c;提高开发效率&#xff0c;优化用户体验。 组成&#xff1a; rqt工具箱组成有三大部分 rqt 核心实现&#xff0c;开发人员无需关注 rqt_common_plugins rqt…

Gated Transformer Networks for Multivariate Time Series Classification

博客贡献人 徐宁 作者 Minghao Liu , Shengqi Ren , Siyuan Ma , Jiahui Jiao , Yizhou Chen , Zhiguang Wang(Facebook AI) and Wei Song∗ 标签 多元时间序列分类&#xff0c;Transformer&#xff0c;门控 摘要 用于时间序列分类的深度学习模型&#xff08;主要是卷积网…

GO网络编程(七):海量用户通信系统5:分层架构

P323开始&#xff08;尚硅谷GO教程&#xff09;老韩又改目录结构了&#xff0c;没办法&#xff0c;和之前一样&#xff0c;先说下目录结构&#xff0c;再给代码&#xff0c;部分代码在之前讲过&#xff0c;还有知识的话由于本人近期很忙&#xff0c;所以这些就不多赘述了&#…

【源码+文档】基于SpringBoot+Vue的健康宝个人健康管理平台

一、项目技术架构&#xff1a; 本项目是一款基于SpringBootVue的个人健康信息管理系统。后端采用SpringBoot架构&#xff0c;前端采用VueElementUI实现页面的快速开发&#xff0c;并使用关系型数据库MySQL存储系统运行数据。本系统分为两种角色&#xff0c;分别是系统管理员&a…

DS入门引言(0)

文章目录 前言一、什么是数据结构&#xff1f;二、什么是算法&#xff1f;三、数据结构与算法的重要性&#xff1f;四、如何学习它们&#xff1f;总结 前言 是的&#xff0c;我又开了一个专栏&#xff0c;数据结构&#xff08;Data Structure&#xff09;&#xff0c;其实数据结…

【人工智能】AI人工智能的重要组成部分,深入解析CNN与RNN两种神经网络的异同与应用场景和区别

文章目录 一、卷积神经网络&#xff08;CNN&#xff09;详解1. 特征与结构CNN的基本结构 2. 应用场景3. 代码示例 二、循环神经网络&#xff08;RNN&#xff09;详解1. 网络结构与特点RNN的基本结构 2. 应用场景3. 代码示例 三、CNN与RNN的异同点1. 相同点2. 不同点 四、CNN与R…

javascript 阿里云,如何返回某个目录的文件

一、效果图 二、实际代码 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>阿里云 OSS 文件列表&…

合约测试用例详解

合约测试的综合案例 第一部分 压力测试(使用caliper工具测试) 1.环境要求 配置基本环境 部署Caliper的计算机需要有外网权限;操作系统版本需要满足以下要求:Ubuntu >= 16.04、CentOS >= 7或MacOS >= 10.14;部署Caliper的计算机需要安装有以下软件:python 2.7…

PMP--冲刺题--解题--91-100

文章目录 11.风险管理--4.实施定量风险分析--题干场景中提到了“专家”&#xff0c;同时即将开始“量化风险”&#xff0c;因此对应的就是“定量风险分析”中的“专家判断”技术。项目经理应先征求各位专家们的意见&#xff0c;以获取最佳的量化风险实施方案。谋定而后动91、 […

wordpress发邮件SMTP服务器配置步骤指南?

wordpress发邮件功能如何优化&#xff1f;怎么用wordpress发信&#xff1f; 由于WordPress默认的邮件发送功能可能不够稳定&#xff0c;配置SMTP服务器成为了许多网站管理员的选择。AokSend将详细介绍如何在WordPress中配置SMTP服务器&#xff0c;以确保邮件能够顺利发送。 w…

Linux-磁盘优化的几个思路

优化前先看看性能指标 I/O 基准测试 fio&#xff08;Flexible I/O Tester&#xff09;正是最常用的文件系统和磁盘 I/O 性能基准测试工具。这类工具非常用&#xff0c;了解即可 应用程序优化 应用程序处于整个 I/O 栈的最上端&#xff0c;它可以通过系统调用&#xff0c;来调…

可持续边缘计算:挑战与未来方向

论文标题&#xff1a;Sustainable edge computing: Challenges and future directions 中文标题&#xff1a;可持续边缘计算&#xff1a;挑战与未来方向 作者信息&#xff1a; Patricia Arroba, Department of Electronic Engineering, Universidad Politcnica de Madrid, Ma…

CANLogFD-ER2数据记录仪数据记录与导出教程

CANLogFD-ER2数据记录仪数据记录与导出教程 VBDSP下载地址&#xff1a; www.njlike.com 数据下载操作视频&#xff1a; 一、引脚定义与指示灯状态 二、设备接线 电脑可以通过网口或WiFi与设备连接&#xff1b;短接通道CAN_H引脚和CAN_R引脚可使能终端电阻。设备接入CAN总线…

PGMP-02项目集管理绩效域

目录 1.概要 2.defintions定义 3.Program Management Performance Domain interactions 交互 4. Organizational Strategy, Portfolio Management, and Program Management Linkage 5. Portfolio and Program Distinctions 区别 6. Program and Project Distinctions区别 …