当前位置:首页 > 科技  > 软件

彻底搞清楚Vue3的DefineExpose宏是如何暴露方法给父组件使用

来源: 责编: 时间:2024-05-28 09:07:05 233观看
导读前言众所周知,当子组件使用setup后,父组件就不能像vue2那样直接就可以访问子组件内的属性和方法。这个时候就需要在子组件内使用defineExpose宏函数来指定想要暴露出去的属性和方法。这篇文章来讲讲defineExpose宏函数

前言

众所周知,当子组件使用setup后,父组件就不能像vue2那样直接就可以访问子组件内的属性和方法。这个时候就需要在子组件内使用defineExpose宏函数来指定想要暴露出去的属性和方法。这篇文章来讲讲defineExpose宏函数是如何暴露出去这些属性和方法给父组件使用。注:本文中使用的vue版本为3.4.19。Wi528资讯网——每日最新资讯28at.com

看个demo

父组件index.vue的代码如下:Wi528资讯网——每日最新资讯28at.com

<template>  <ChildDemo ref="child" />  <button @click="handleClick">调用子组件的validate方法</button></template><script setup lang="ts">import ChildDemo from "./child.vue";import { ref } from "vue";const child = ref();function handleClick() {  console.log(child.value.validate);  child.value.validate?.();}</script>

上面的代码很简单,通过ref拿到子组件的实例赋值给child变量。然后在按钮的click事件中打印出子组件的validate方法和执行validate方法。Wi528资讯网——每日最新资讯28at.com

再来看看子组件child.vue不使用defineExpose宏的例子,代码如下:Wi528资讯网——每日最新资讯28at.com

<template></template><script setup>function validate() {  console.log("执行子组件validate方法");}</script>

在浏览器中点击父组件的button按钮,可以看到控制台中打印的是undefined,并且子组件内的validate方法也没有执行。因为子组件使用了setup,默认是不会暴露setup中定义的属性和方法。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

我们再来看看子组件child.vue使用defineExpose宏的例子,代码如下:Wi528资讯网——每日最新资讯28at.com

<template></template><script setup>function validate() {  console.log("执行子组件validate方法");}defineExpose({  validate,});</script>

在浏览器中点击父组件的button按钮,可以看到控制台中打印的不再是undefined,子组件内的validate方法也执行了。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

编译后的代码

首先需要在浏览器中找到编译后的使用defineExpose宏的child.vue文件,在network面板中找到child.vue,然后右键点击Open in Sources panel就可以在source面板中找到编译后的child.vue。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

为了要在浏览器中debug,我们还需要在设置中关闭浏览器的javascript source map,如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

现在我们来看看编译后的child.vue文件,代码如下:Wi528资讯网——每日最新资讯28at.com

const _sfc_main = {  __name: "child",  setup(__props, { expose: __expose }) {    function validate() {      console.log("执行子组件validate方法");    }    __expose({      validate,    });    const __returned__ = { validate };    return __returned__;  },};function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {  return null;}_sfc_main.render = _sfc_render;export default _sfc_main;

从上面可以看到_sfc_main对象中的setup对应的就是我们源代码<script setup>中的内容,并且defineExpose宏函数也不在了,变成了一个__expose方法(defineExpose宏函数如何编译成__expose方法我们会在下一篇文章讲)。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

expose方法

给__expose方法打个断点,刷新页面此时断点停留在__expose方法上面。点击step into进入到__expose方法内部,如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

进入到__expose方法内部,我们发现__expose方法是在一个createSetupContext函数中定义的。在我们这个场景中createSetupContext函数简化后的代码如下:Wi528资讯网——每日最新资讯28at.com

function createSetupContext(instance) {  const expose = (exposed) => {    instance.exposed = exposed || {};  };  return Object.freeze({    // ...省略    expose,  });}

我们先来看看函数中的instance变量,我想你通过名字应该已经猜到了他就是当前vue实例对象。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

在vue实例对象中有我们熟悉的data方法、directives和componens属性等。Wi528资讯网——每日最新资讯28at.com

在expose函数内部做的事情也很简单,将子组件需要暴露的属性或者方法组成的对象赋值给vue实例上的exposed属性。Wi528资讯网——每日最新资讯28at.com

父组件访问子组件的validate方法

在vue3中想要访问子组件需要使用特殊的 ref attribute,在我们这个例子中就是使用<ChildDemo ref="child" />。这样使用后就可以使用child变量访问子组件,其实在这里child变量的值就是一个名为getExposeProxy函数的返回值(后面的文章中会去详细讲解ref attribute是如何访问子组件)。Wi528资讯网——每日最新资讯28at.com

getExposeProxy函数的代码如下:Wi528资讯网——每日最新资讯28at.com

function getExposeProxy(instance) {  if (instance.exposed) {    return (      instance.exposeProxy ||      (instance.exposeProxy = new Proxy(proxyRefs(markRaw(instance.exposed)), {        get(target, key) {          if (key in target) {            return target[key];          } else if (key in publicPropertiesMap) {            return publicPropertiesMap[key](instance);          }        },        has(target, key) {          // ...省略        },      }))    );  }}

前面我们讲过了defineExpose宏函数中定义了想要暴露出来的属性和方法,经过编译后defineExpose宏函数变成了__expose方法。执行__expose方法后会将子组件想要暴露的属性或者方法组成的对象赋值给vue实例上的exposed属性,也就是instance.exposed。Wi528资讯网——每日最新资讯28at.com

在上面的getExposeProxy函数中就是返回了instance.exposed的Proxy对象,当我们使用child.value.validate访问子组件的validate方法,其实就是访问的是instance.exposed对象中的validate方法,而instance.exposed中的validate方法就是defineExpose宏函数暴露的validate方法。如下图:Wi528资讯网——每日最新资讯28at.com

图片图片Wi528资讯网——每日最新资讯28at.com

总结

父组件想要访问子组件暴露的validate方法主要分为下面四步:Wi528资讯网——每日最新资讯28at.com

  • 子组件使用defineExpose宏函数声明想要暴露validate方法。
  • defineExpose宏函数经过编译后变成__expose方法。
  • 执行__expose方法将子组件需要暴露的属性或者方法组成的对象赋值给子组件vue实例上的exposed属性,也就是instance.exposed。
  • 父组件使用ref访问子组件的validate方法,也就是访问child.value.validate。其实访问的就是上一步的instance.exposed.validate方法,最终访问的就是defineExpose宏函数中暴露的validate方法。

点击下方卡片关注我,给自己一个进阶vue的机会。Wi528资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-91161-0.html彻底搞清楚Vue3的DefineExpose宏是如何暴露方法给父组件使用

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 从基础概念到进阶思考,完整的递归思维学习

下一篇: Python 操作系统交互的 15 个实用命令

标签:
  • 热门焦点
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 5月安卓手机好评榜:魅族20 Pro夺冠

    性能榜和性价比榜之后,我们来看最后的安卓手机好评榜,数据来源安兔兔评测,收集时间2023年5月1日至5月31日,仅限国内市场。第一名:魅族20 Pro好评率:97.50%不得不感慨魅族老品牌还
  • 容量越大越不坏?24万块硬盘故障率报告公布 这些产品零故障

    8月5日消息,云存储服务商Backblaze发布了最新的硬盘故障率报告,年故障率有所上升。Backblaze发布的硬盘季度统计数据,其中包括故障率等重要方面。这些结
  • SpringBoot中使用Cache提升接口性能详解

    环境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架从 3.1 开始,对 Spring 应用程序提供了透明式添加缓存的支持。和事务支持一样,抽象缓存允许一致地使用各
  • 从零到英雄:高并发与性能优化的神奇之旅

    作者 | 波哥审校 | 重楼作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得
  • 零售大模型“干中学”,攀爬数字化珠峰

    文/侯煜编辑/cc来源/华尔街科技眼对于绝大多数登山爱好者而言,攀爬珠穆朗玛峰可谓终极目标。攀登珠峰的商业路线有两条,一是尼泊尔境内的南坡路线,一是中国境内的北坡路线。相
  • 中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 冯提莫签约抖音公会 前“斗鱼一姐”消失在直播间

    来源:直播观察提起&ldquo;冯提莫&rdquo;这个名字,很多网友或许听过,但应该不记得她是哪位主播了。其实,作为曾经的&ldquo;斗鱼一姐&rdquo;,冯提莫在游戏直播的年代影响力不输于现
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
Top