深入解析Vue3 defineExpose

Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但是这种做法存在很多弊端,例如,它们只能用于父子组件之间的通信、只能访问父组件实例上的属性或方法、难以在slot作用域中继承等等。现在,使用 `defineExpose` 你可以轻松地将值暴露给自己的组件外部,而不必借助其他API。

一、什么是defineExpose

在Vue中,组件API分为两类,一类是外部API,如Vue.component、directives、mixins、props、inject等,他们允许父组件对子组件产生影响。另一类是内部API,例如`$emit`、`$attrs`、`$listeners`等,它们允许子组件对父组件产生影响。而 defineExpose 就是用来将子组件的内部API,变成外部API。

通过 `defineExpose`,子组件将自己的一些内部状态或方法暴露给父级,达到和$emit相同的效果。

二、defineExpose的使用方法

定义一个子组件:

import { defineComponent, ref, defineExpose } from 'vue'
export default defineComponent({
  setup() {
    const count = ref(0)
    const increment = () => {
      count.value++
    }
  
    defineExpose({
      count,
      increment
    })
  
    return {
      count,
      increment
    }
  }
})

在这个组件中,我们定义了一个计数器的变量和一个`increment`方法,并通过 `defineExpose` 将这些内容暴露出去。

然后在父组件中,我们可以通过`$refs`引用子组件,直接访问子组件的属性和方法:

import { ref } from 'vue'
import ChildComponent from '@/components/ChildComponent.vue'

export default {
  setup() {
     const childRef = ref(null)
     const handleClick = () => {
       console.log(childRef.count)
       childRef.increment()
     }
  
    return {
      childRef,
      handleClick
    }
  },
  
  components: {
    ChildComponent
  }
}

在父组件中,我们通过 `components` 属性注册了子组件,在 setup 函数中定义了一个 `childRef` 引用,并且通过 `handleClick` 方法来访问子组件中的 `count` 属性和 `increment` 方法。

三、defineExpose为多个组件间的通信带来的便利

除了简化父子组件之间的通信之外,`defineExpose`还可以为多个组件之间的通信带来便利。假设我们有两个组件:`Menu` 和 `MenuItem`。 `Menu` 组件作为容器,包含若干个 `MenuItem` 组件,每个 `MenuItem` 组件有一个选项名称和一个选项的状态。我们希望父组件可以直接操作每个菜单项的选项状态。

首先,我们给 MenuItem 组件添加一个 selected 属性,并且在 setup 函数中定义一个 toggle 方法,当使用者点击菜单项的时候,会切换 selected 属性的值。

import { defineComponent, ref, defineExpose } from 'vue'

export default defineComponent({
  props: {
    label: {
      type: String,
      required: true
    },
    defaultSelected: {
      type: Boolean,
      default: false
    }
  },
  setup(props) {
    const selected = ref(props.defaultSelected)
    const toggle = () => {
      selected.value = !selected.value
    }
    
    defineExpose({
      selected,
      toggle
    })
    
    return {
      selected,
      toggle
    }
  }
})

然后在 Menu 组件中,我们可以使用`$refs`引用所有的 MenuItem 项,并暴露 `selected` 属性和 `toggle` 方法。

 import { ref, defineComponent } from 'vue'
 import MenuItem from './MenuItem.vue'
 
 export default defineComponent({
   components: {
     MenuItem,
   },
   setup() {
     const items = ref([])
 
     const toggleAll = () => {
       items.value.forEach(item => {
         item.toggle()
       })
     }
 
     return {
       items,
       toggleAll
     }
   },
  
   mounted() {
     this.items = this.$refs.menuItems.map(item => item)
   },
   
   defineExpose({
     items: items,
     toggleAll: toggleAll
   })
 })

最后在 Menu 组件的父组件或者其他组件中,我们就可以使用 `$refs` 引用 Menu 组件,并且可以直接访问到 `toggleAll` 方法和每个菜单项的 `selected` 属性。

选项


原创文章,作者:GUVNF,如若转载,请注明出处:https://www.506064.com/n/373213.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
GUVNFGUVNF
上一篇 2025-04-25 15:26
下一篇 2025-04-25 15:26

相关推荐

  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25
  • 深入了解scala-maven-plugin

    一、简介 Scala-maven-plugin 是一个创造和管理 Scala 项目的maven插件,它可以自动生成基本项目结构、依赖配置、Scala文件等。使用它可以使我们专注于代…

    编程 2025-04-25
  • 深入了解LaTeX的脚注(latexfootnote)

    一、基本介绍 LaTeX作为一种排版软件,具有各种各样的功能,其中脚注(footnote)是一个十分重要的功能之一。在LaTeX中,脚注是用命令latexfootnote来实现的。…

    编程 2025-04-25
  • 深入剖析MapStruct未生成实现类问题

    一、MapStruct简介 MapStruct是一个Java bean映射器,它通过注解和代码生成来在Java bean之间转换成本类代码,实现类型安全,简单而不失灵活。 作为一个…

    编程 2025-04-25
  • 深入了解Python包

    一、包的概念 Python中一个程序就是一个模块,而一个模块可以引入另一个模块,这样就形成了包。包就是有多个模块组成的一个大模块,也可以看做是一个文件夹。包可以有效地组织代码和数据…

    编程 2025-04-25
  • 深入探讨冯诺依曼原理

    一、原理概述 冯诺依曼原理,又称“存储程序控制原理”,是指计算机的程序和数据都存储在同一个存储器中,并且通过一个统一的总线来传输数据。这个原理的提出,是计算机科学发展中的重大进展,…

    编程 2025-04-25
  • 深入理解Python字符串r

    一、r字符串的基本概念 r字符串(raw字符串)是指在Python中,以字母r为前缀的字符串。r字符串中的反斜杠(\)不会被转义,而是被当作普通字符处理,这使得r字符串可以非常方便…

    编程 2025-04-25
  • 深入剖析slice方法

    一、切片介绍 slice方法是数组的一个重要成员之一,用来截取数组中的一部分,并返回一个新的数组。它最常用的形式是array.slice(start, end)。 其中start和…

    编程 2025-04-25

发表回复

登录后才能评论