成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

徹底搞清楚Vue3的DefineExpose宏是如何暴露方法給父組件使用

開發(fā) 前端
在瀏覽器中點(diǎn)擊父組件的button按鈕,可以看到控制臺中打印的是undefined,并且子組件內(nèi)的validate方法也沒有執(zhí)行。因?yàn)樽咏M件使用了setup,默認(rèn)是不會暴露setup中定義的屬性和方法。

前言

眾所周知,當(dāng)子組件使用setup后,父組件就不能像vue2那樣直接就可以訪問子組件內(nèi)的屬性和方法。這個(gè)時(shí)候就需要在子組件內(nèi)使用defineExpose宏函數(shù)來指定想要暴露出去的屬性和方法。這篇文章來講講defineExpose宏函數(shù)是如何暴露出去這些屬性和方法給父組件使用。注:本文中使用的vue版本為3.4.19。

看個(gè)demo

父組件index.vue的代碼如下:

<template>
  <ChildDemo ref="child" />
  <button @click="handleClick">調(diào)用子組件的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拿到子組件的實(shí)例賦值給child變量。然后在按鈕的click事件中打印出子組件的validate方法和執(zhí)行validate方法。

再來看看子組件child.vue不使用defineExpose宏的例子,代碼如下:

<template></template>

<script setup>
function validate() {
  console.log("執(zhí)行子組件validate方法");
}
</script>

在瀏覽器中點(diǎn)擊父組件的button按鈕,可以看到控制臺中打印的是undefined,并且子組件內(nèi)的validate方法也沒有執(zhí)行。因?yàn)樽咏M件使用了setup,默認(rèn)是不會暴露setup中定義的屬性和方法。如下圖:

圖片圖片

我們再來看看子組件child.vue使用defineExpose宏的例子,代碼如下:

<template></template>

<script setup>
function validate() {
  console.log("執(zhí)行子組件validate方法");
}

defineExpose({
  validate,
});
</script>

在瀏覽器中點(diǎn)擊父組件的button按鈕,可以看到控制臺中打印的不再是undefined,子組件內(nèi)的validate方法也執(zhí)行了。如下圖:

圖片圖片

編譯后的代碼

首先需要在瀏覽器中找到編譯后的使用defineExpose宏的child.vue文件,在network面板中找到child.vue,然后右鍵點(diǎn)擊Open in Sources panel就可以在source面板中找到編譯后的child.vue。如下圖:

圖片圖片

為了要在瀏覽器中debug,我們還需要在設(shè)置中關(guān)閉瀏覽器的javascript source map,如下圖:

圖片圖片

現(xiàn)在我們來看看編譯后的child.vue文件,代碼如下:

const _sfc_main = {
  __name: "child",
  setup(__props, { expose: __expose }) {
    function validate() {
      console.log("執(zhí)行子組件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對應(yīng)的就是我們源代碼<script setup>中的內(nèi)容,并且defineExpose宏函數(shù)也不在了,變成了一個(gè)__expose方法(defineExpose宏函數(shù)如何編譯成__expose方法我們會在下一篇文章講)。如下圖:

圖片圖片

expose方法

給__expose方法打個(gè)斷點(diǎn),刷新頁面此時(shí)斷點(diǎn)停留在__expose方法上面。點(diǎn)擊step into進(jìn)入到__expose方法內(nèi)部,如下圖:

圖片圖片

進(jìn)入到__expose方法內(nèi)部,我們發(fā)現(xiàn)__expose方法是在一個(gè)createSetupContext函數(shù)中定義的。在我們這個(gè)場景中createSetupContext函數(shù)簡化后的代碼如下:

function createSetupContext(instance) {
  const expose = (exposed) => {
    instance.exposed = exposed || {};
  };

  return Object.freeze({
    // ...省略
    expose,
  });
}

我們先來看看函數(shù)中的instance變量,我想你通過名字應(yīng)該已經(jīng)猜到了他就是當(dāng)前vue實(shí)例對象。如下圖:

圖片圖片

在vue實(shí)例對象中有我們熟悉的data方法、directives和componens屬性等。

在expose函數(shù)內(nèi)部做的事情也很簡單,將子組件需要暴露的屬性或者方法組成的對象賦值給vue實(shí)例上的exposed屬性。

父組件訪問子組件的validate方法

在vue3中想要訪問子組件需要使用特殊的 ref attribute,在我們這個(gè)例子中就是使用<ChildDemo ref="child" />。這樣使用后就可以使用child變量訪問子組件,其實(shí)在這里child變量的值就是一個(gè)名為getExposeProxy函數(shù)的返回值(后面的文章中會去詳細(xì)講解ref attribute是如何訪問子組件)。

getExposeProxy函數(shù)的代碼如下:

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宏函數(shù)中定義了想要暴露出來的屬性和方法,經(jīng)過編譯后defineExpose宏函數(shù)變成了__expose方法。執(zhí)行__expose方法后會將子組件想要暴露的屬性或者方法組成的對象賦值給vue實(shí)例上的exposed屬性,也就是instance.exposed。

在上面的getExposeProxy函數(shù)中就是返回了instance.exposed的Proxy對象,當(dāng)我們使用child.value.validate訪問子組件的validate方法,其實(shí)就是訪問的是instance.exposed對象中的validate方法,而instance.exposed中的validate方法就是defineExpose宏函數(shù)暴露的validate方法。如下圖:

圖片圖片

總結(jié)

父組件想要訪問子組件暴露的validate方法主要分為下面四步:

  • 子組件使用defineExpose宏函數(shù)聲明想要暴露validate方法。
  • defineExpose宏函數(shù)經(jīng)過編譯后變成__expose方法。
  • 執(zhí)行__expose方法將子組件需要暴露的屬性或者方法組成的對象賦值給子組件vue實(shí)例上的exposed屬性,也就是instance.exposed。
  • 父組件使用ref訪問子組件的validate方法,也就是訪問child.value.validate。其實(shí)訪問的就是上一步的instance.exposed.validate方法,最終訪問的就是defineExpose宏函數(shù)中暴露的validate方法。

點(diǎn)擊下方卡片關(guān)注我,給自己一個(gè)進(jìn)階vue的機(jī)會。

責(zé)任編輯:武曉燕 來源: 前端歐陽
相關(guān)推薦

2011-06-22 09:37:03

桌面虛擬化存儲

2020-11-16 08:37:16

MariaDB性能優(yōu)化

2020-12-16 11:09:27

JavaScript語言開發(fā)

2020-12-31 07:57:25

JVM操作代碼

2018-07-19 10:16:25

華光昱能

2024-08-13 09:26:07

2020-04-11 11:21:22

留存分析模型分析

2018-06-26 14:42:10

StringJava數(shù)據(jù)

2021-09-01 09:32:40

工具

2017-08-15 08:27:48

云備份問題恢復(fù)

2025-04-25 11:30:00

vector編程C++

2021-01-19 06:43:10

Netty框架網(wǎng)絡(luò)技術(shù)

2018-06-20 10:43:58

云端霧端霧計(jì)算

2015-10-12 10:01:26

AndroidWindows應(yīng)用Windows 10

2011-03-07 17:44:59

中小企業(yè)實(shí)施虛擬化

2022-08-08 08:48:15

Go版本偽版本

2019-07-26 15:49:25

代碼開發(fā)工具

2020-04-28 17:26:04

監(jiān)督學(xué)習(xí)無監(jiān)督學(xué)習(xí)機(jī)器學(xué)習(xí)

2022-11-16 14:02:44

2022-07-27 08:40:06

父子組件VUE3
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 1000部精品久久久久久久久 | 欧美色专区 | 久久av网 | www.夜夜草| 国产精品不卡 | 亚洲网站在线观看 | 亚洲欧美在线一区 | 亚洲精品99久久久久久 | 国产美女免费视频 | 久久久国产一区二区三区四区小说 | 欧美videosex性极品hd | 久久久91精品国产一区二区三区 | 亚洲色图在线观看 | 日韩一区二区三区视频在线观看 | 成人在线观看欧美 | 中文字幕免费视频 | 亚洲免费在线视频 | 国产精品久久久久久久久久久免费看 | 欧美精品一区久久 | 国产精品久久亚洲 | 成人夜晚看av| 久久999 | 久久狠狠| 91网站在线播放 | 一级欧美一级日韩片免费观看 | 亚洲国产成人久久久 | 国产精品日韩在线观看一区二区 | 夜夜爽99久久国产综合精品女不卡 | 精品福利在线视频 | 精品久久久久久久人人人人传媒 | 18成人在线观看 | 综合天天久久 | 欧美成人a∨高清免费观看 欧美日韩中 | 99精品视频一区二区三区 | 黄色成人亚洲 | 欧美精品在线一区 | 精品久久一 | 亚洲一区二区三区久久久 | 久久这里只有精品首页 | 国产 日韩 欧美 制服 另类 | 国产一区二区小视频 |