简单的聊一聊 Vue3.2 中新出的 expose 是做啥用的?

article/2025/10/14 2:39:50

712864d00b4087f4c7ac0b8297566113.jpeg

随着Vue 3.2的发布,一个新的组合工具提供给我们,叫做 expose

你是否曾经创建过一个需要向模板提供一些方法和属性的组件,但又希望这些方法对组件是私有的,不能被父类调用?

如果你在开发一个开源的组件或库,你有可能想保持一些内部方法的私有性。在Vue 3.2之前,这并不容易实现,因为所有在选项API中声明的方法或数据等都是公开的,所以模板可以访问它。

组合API也是如此。我们从setup方法中返回的所有东西都可以被父类直接访问。

组合 API

让我们看一个实际的例子。想象一下,我们有一个组件,它创建了一个计数器,每一秒都会更新这个计数器。

** MyCounter.vue**

<template>
    <p>Counter: {{ counter }}</p>

    <button @click="reset">Reset</button>
    <button @click="terminate">☠️</button>
</template>

<script>
import { ref } from 'vue'

export default {
  setup () {
    const counter = ref(0)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      clearInterval(interval)
    }

    return {
      counter,
      reset,
      terminate
    }
  }
}
</script>

从组合的角度来看,我希望父级组件能够在需要时直接调用reset方法--但我希望保持terminate 函数和 counter 的引用只对组件可用。

如果我们把这个组件实例化到一个父类中,例如 App.vue,并给它附加一个 ref 引用,我们可以很容易地让父类调用 reset 方法,因为当我们从 setup 中返回它时,它已经和 terminate 一起被暴露了。

App.vue

<template>
  <MyCounter ref="counter" />

  <button @click="reset">Reset from parent</button>
  <button @click="terminate">Terminate from parent</button>
</template>

<script>
import MyCounter from '@/components/MyCounter.vue'

export default {
  name: 'App',
  components: {
    MyCounter
  },
  methods: {
    reset () {
      this.$refs.counter.reset()
    },
    terminate () {
      this.$refs.counter.terminate()
    }
  }
}
</script>

如果现在运行这个,并单击重置或终止按钮,两者都可以工作。

让我们明确说明我们要向父类暴露(expose)的内容,以便只有 reset 函数可用。

** MyCounter.vue**

<script>
import { ref } from 'vue'

export default {
  setup (props, context) {
    const counter = ref(null)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      console.log(interval)
      clearInterval(interval)
    }

    context.expose({ reset })

    return {
      counter,
      reset,
      terminate
    }
  }
}
</script>

这里,我们在setup函数中加入了 propscontext 参数。我们需要有可用的上下文,因为这是 expose 函数的位置。我们也可以像这样使用重构: { expose }

接下来,我们使用 context.expose 来声明一个我们想要向实例化这个组件的父类公开的元素对象;在这个例子中,我们只打算让 reset 功能可用。

如果我们再次运行这个例子,并点击 "Terminate from parent" 按钮,我们会得到一个错误。

Uncaught TypeError: this.$refs.counter.terminate is not a function

terminate 功能不再可用,我们的私有API现在也无法访问了。

选项API

上面我们在 composition API 使用 exponse,但在options API中也可以使用这个方法。我们可以把它改写成如下。

//  MyCounter.vue


export default {
  created () { ... },
  data: () => ({ counter: null }),
  methods: {
    reset () { ... },
    terminate () { ... }
  },
  expose: ['reset']
}

注意,我们添加了一个新的选项API属性expose,允许我们传入一个数组,其中字符串'reset'是我们公开的函数的名称。

组合API 渲染功能

创建一个强大脸灵活的组件的方法是利用渲染函数的力量。这对Vue 3来说并不新鲜,但是随着composition API的建立,我们现在可以灵活地从setup方法中直接返回组合API h 函数。

这就产生了一个问题,因为在我们的setup函数中,整个return语句只是包含组件正在创建的节点的 h 方法。

如果在这个时候我们选择向父类 expose 一些东西,我们就会遇到与我们之前看到的相反的问题。没有任何东西被暴露,因为除了DOM元素,没有任何东西被返回。

让我们重写 MyCounter.vue 组件来使用这个方法。

<script>
// The template has been deleted
import { ref, h } from 'vue'

export default {
  setup (props, context) {
    const counter = ref(0)

    const interval = setInterval(() => {
      counter.value++
    }, 1000)

    const reset = () => {
      counter.value = 0
    }

    const terminate = () => {
      clearInterval(interval)
    }

    // context.expose({ reset })

    return () => h('div', [
      h('p', `Counter: ${counter.value}`),
      h('button', { onClick: reset }, 'Reset'),
      h('button', { onClick: terminate }, 'Terminate')
    ])
  }
}
</script>

注意,我们在顶部从Vue导入了 h,因为我们需要用它来创建我们的DOM元素。

为了说明问题,暂时注释了context.expose方法。

现在的 return 语句复制了我们之前的 <template> 的DOM结构,如果我们运行这个例子,我们能够正确点击元素上的重置和终止按钮。

然而,如果我们现在点击 "Reset from parent"按钮,我们会遇到一个错误。

Uncaught TypeError: this.$refs.counter.reset is not a function

reset方法不再被暴露,因为它没有被setup函数返回。为了解决这个问题,我们需要取消对context.expose的调用,使其再次可用。

总结

新的 expose 方法是非常直观的,而且很容易在我们的组件中实现。它清除了一些非常重要的组成问题,这些问题在过去甚至需要重写一个完整的组件,所以即使它不是你日常使用的API,它也是值得收藏在我们文件夹中吃灰。


作者:Marina Mosti  译者:前端小智  来源:vuemastery  原文:https://www.vuemastery.com/blog/undrstanding-vue-3-expose/


http://chatgpt.dhexx.cn/article/Bn0ck1eJ.shtml

相关文章

Android gson解析@SerializedName、transient、@Expose

目录 SerializedName和transient Expose SerializedName和transient SerializedName 自定义序列化与反序列化过程中json数据的的key transient 加这个关键字表示这个字段 不会参与任何的序列化与反序列化 看代码 该商品类,name字段加上SerializedName("goodsName"…

kubectl 命令详解(七):expose

一、命令作用 将资源暴露为新的Kubernetes Service。 指定deployment、service、replica set、replication controller或pod &#xff0c;并使用该资源的选择器作为指定端口上新服务的选择器。deployment 或 replica set只有当其选择器可转换为service支持的选择器时&#xf…

Dockerfile EXPOSE指令 语法解析

Docker容器启动后&#xff0c;需要宿主机和容器端口进行映射&#xff0c;以便容器内服务对外暴露&#xff0c;这可以在启动是通过docker run -p host:port ...指定&#xff0c;也可以在镜像构建时通过dockerfile的EXPOSE指令指定&#xff0c;本文本来具体对EXPOSE指令进行解析。…

Dockerfile中的expose到底有啥用

如题&#xff0c;看过Dockerfile常识的肯定都知道这个EXPOSE指令是暴露容器的端口。 docker run 的时候指定 -P 或者 -p 将容器的端口映射到宿主机上。这样外界访问宿主机就可以获取到容器提供的服务了。 -P命令可以结合这个dockerfile文件中的EXPOSE暴露的端口。会将容器…

Dockerfile(6) - EXPOSE 指令详解

EXPOSE 通知 Docker 容器在运行时监听指定的网络端口 EXPOSE 端口号 EXPOSE 端口号/协议 默认协议是 TCP 同时在 TCP、UDP 上暴露端口 EXPOSE 80/tcp EXPOSE 80/udp EXPOSE 原理 个人理解&#xff1a;EXPOSE 暴露的端口更像是指明了该容器提供的服务需要用到的端口EXPOSE 并不…

2019中兴捧月·初赛心得

2019中兴捧月初赛心得 原文链接&#xff1a;https://hey-yahei.cn/2019/05/22/zte_challenge_preliminary/ 赛题背景 自从 Alex Krizhevsky 夺得 ILSVRC 2012 ImageNet 图像分类竞赛的冠军后&#xff0c;深度卷积神经网络在图像分类、物体检测、语义分割、目标跟踪等多个计算…

2019中兴捧月之智能音频处理参赛总结

抱着免笔试的心态参加了中兴捧月比赛&#xff0c;赛题一下来&#xff0c;呦&#xff01;题目可选余地很大&#xff0c;稳了&#xff01;看完题之后&#xff0c;凉了&#xff01;再见&#xff0c;中兴。。。 正题开始&#xff0c;博主选的是智能音频识别&#xff0c;题目给了几段…

算法4-中兴捧月杯热身赛1素数判断-热身赛2亲和串-热身赛3旅游路线-

题目1&#xff1a;素数判断 需求 给定一个数n&#xff0c;要求判断其是否为素数(0,1&#xff0c;负数都是非素数)。输入描述:测试数据有多组&#xff0c;每组输入一个数n。输出描述:对于每组输入,若是素数则输出yes&#xff0c;否则输入no。 样例1: 输入:13输出:yes 代码 //…

2021中兴捧月神算师算法赛,4-24第一场,第四题:D-换队伍,2021-4-28

第四题&#xff1a;D-换队伍 分析&#xff1a; 1.问题本身很简单&#xff0c;也只有两条队伍&#xff0c;一个队伍中的人换到另一个队伍的末尾。问题在于对其他人排队位置的保存和排序。 2.用什么数据结构进行保存&#xff0c;是一个很关键的问题&#xff0c;对问题解决的方法和…

中兴捧月算法挑战赛-RAW夜景图像去噪总结

最终排名 85/1159 网址&#xff1a;https://zte.hina.com/zte/denoise 无缘复赛&#xff0c;太菜了&#xff0c;不好意思说自己学去噪的了&#xff0c;代码会开源&#xff0c;但是感觉没什么人看吧 尝试过的模型 DnCNN&#xff1a;很差&#xff0c;0分UNet&#xff1a;很蓝…

2021中兴捧月神算师算法赛,4-24第一场,第二题:B - 切绳子,2021-4-27

第二题&#xff1a;B - 切绳子 题目如下图所示&#xff1a; 这道题目难度中等&#xff0c;但是有很多细节要注意。 分析&#xff1a; 1.首先数据类型问题&#xff0c; 1<n<1e18,这个显然超过了int的长度65535&#xff0c;需要使用big int 或者是long long 型进行定义…

中兴捧月算法-切绳子

中兴捧月算法-切绳子 题目描述 来源&#xff1a;牛客网 示例一&#xff1a;

中兴捧月比赛DIJKSTRA派算法说明

因为文章包含太多公式&#xff0c;无法复制&#xff0c;所以只能截图 我现在不知道怎么传源码&#xff0c;代码的话如果有人要&#xff0c;留言QQ 输出的次优解路径为&#xff1a; S->N2->N4->N5->N3->N7->N8->N14->N13->N12-…

2019中兴捧月·总决赛心得

2019中兴捧月总决赛心得 原文链接&#xff1a;https://hey-yahei.cn/2019/05/25/zte_challenge_final/ 赛题背景 与初赛类似&#xff0c;不过初赛更多关注的是加速&#xff0c;而总决赛更关注的是压缩。 原始模型是一个简单的3x112x112输入大小的resnet18&#xff0c;人脸识…

2020年中兴捧月傅里叶派决赛题目

目录 题目&#xff1a; 模型建立 题目分析 注意的小问题 计算结果 代码 模型改进和精细预测 写在最后 题目&#xff1a; 假设&#xff1a; 病毒正在一个居民总数为N100,000, 的城市里扩散。在我们研究的时间段内&#xff08;300天&#xff09;&#xff0c;没有新生儿…

2022中兴捧月算法挑战赛(RAW图像去噪)——初赛到决赛总结与反思

文章目录 1. 初赛经历&炼丹详情1.1 初赛经历1.2 炼丹详情 2、复赛经历&反思与总结2.1 复赛经历2.2 复赛反思 3、决赛经历&反思与总结3.1 决赛题目3.2 决赛思路总结3.3 冠军方案记录3.4 决赛经历3.5 决赛反思 1. 初赛经历&炼丹详情 1.1 初赛经历 最后分数57.2…

2020中兴捧月算法大赛迪杰斯特拉赛道初赛题解

目录 摘要1 程序中使用的数据结构1.1 几个基本数据类型1.2 车道(Lane)1.3 道路(Road)1.4 站点(Station)1.5 货物(Goods)1.6 系统资源(SystemResource)1.7 物流系统(LogisticsSystem) 2 算法思路2.1 初赛初版&#xff1a;路由表、深度优先搜索、路径惩罚2.1.1 搜索策略2.1.2 路径…

中兴捧月营销精英挑战赛回顾

先上图 为期四天的比赛结束了&#xff0c;把这次比赛的收获做一个总结和分享。希望能帮上后面有需要的同学吧。 主要内容分为比赛流程、决赛内容和心得体会三部分。 一.比赛流程 比赛流程分为三部分&#xff0c;初赛、复赛和决赛。初赛开始需要每位同学从瑞伊、加勒斯和奥格…

2023中兴捧月图像赛道-任意尺度盲超分初赛第三方案

任意尺度盲超分-初赛第三方案 吐槽篇方案篇一、左脚踩右脚二、梯度攻击 建议篇 吐槽篇 正文内容.正式讲述方案之前&#xff0c;容我先吐槽两句&#xff0c;真tm的是比赛&#xff0c;纯纯ex人。学历厂就别打着以赛招聘的口号&#xff0c;要985计算机的直接去他们学校里宣讲嘛&am…

中兴捧月之旅

上个月底&#xff0c;我怀着激动的心情来到古都西安参加了第十一届中兴捧月算法大赛的全国总决赛&#xff0c;因为这是我第一次参加的线下封闭开发的现场竞赛&#xff0c;特以此文记录这趟快乐的西安之旅。 中兴捧月是中兴通讯公司举办的大型算法比赛&#xff0c;今年共有6大赛…