vue3沒了$children馏锡,如何獲取子組件?割择?眷篇?

vue3已經(jīng)推出很久了,相信大家也都體驗(yàn)過了荔泳,變化很大蕉饼,尤其是composition Api的出現(xiàn),而且對typescript的支持更好了玛歌,但是寫慣了vue2的我昧港,在使用setup的時候,碰到了一個問題:setup里面沒有this支子,而且廢除了$children创肥,那么我要如何獲取當(dāng)前組件的實(shí)例和獲取當(dāng)前組件的子組件?值朋?
本文創(chuàng)建兩個演示示例組件:Parent.vue叹侄、Children,vue
一、獲取當(dāng)前組件
vue3提供了一個getCurrentInstance方法用來獲取當(dāng)前組件的實(shí)例

<template>
  <div class="parent">
    {{ msg }}
  </div>
</template>

<script lang="ts">
import { defineComponent, getCurrentInstance } from "vue";

export default defineComponent({
  setup() {
    const instance = getCurrentInstance();
    console.log(instance);
    let msg = "我是父組件";
    return { msg };
  },
});
</script>

<style scoped>
.parent {
  color: rgb(233, 35, 0);
  position: relative;
  font-size: 30px;
}
</style>

來看頁面


instance.png

控制臺中打印出的對象就是當(dāng)前組件的實(shí)例昨登,拿到這個實(shí)例對象之后就能調(diào)用里面的方法趾代,比如parent,props等數(shù)據(jù)丰辣,這個就是一個方法的事兒

一撒强、獲取當(dāng)前組件的子組件實(shí)例
先來看看vue3官網(wǎng)對$children的說明

在 3.x 中,$children property 已被移除笙什,且不再支持飘哨。如果你需要訪問子組件實(shí)例,我們建議使用 $refs琐凭。

意思就是說推薦我們使用ref對子組件進(jìn)行綁定芽隆,然后訪問子組件
在Children.vue中家點(diǎn)東西

// Children.vue
<template>
  <div class="children">
    <h2>我是子組件</h2>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  setup() {
    return {};
  },
});
</script>

父組件注冊Children

<template>
  <div class="parent">
    <Children></Children>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import Children from "./Children.vue";

export default defineComponent({
  components: {
    Children,
  },
  setup() {
    return {};
  },
});
</script>

然后就能看到子組件的內(nèi)容了


view.png

下面就通過ref來綁定子組件,要在vue中引入ref淘正。需要注意的是setup的執(zhí)行是早于mounted摆马,甚至早于created生命周期的,所以通過ref綁定成功之后需要在mounted生命周期才能訪問到你綁定的子組件的

<template>
  <div class="parent">
    <Children ref="childrenRef"></Children>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import Children from "./Children.vue";

export default defineComponent({
  components: {
    Children,
  },
  setup() {
    const childrenRef = ref(null);

    onMounted(() => {
      console.log(childrenRef);
      console.log(childrenRef.value);
    });

    return { childrenRef };
  },
});
</script>

chidren.png

調(diào)用子組件的方法
setup的第二個參數(shù)上有一個expose 屬性鸿吆,這是vue3.2+才出現(xiàn)的內(nèi)容囤采,通過expose 可以將該組件內(nèi)部的一些方法等對外進(jìn)行暴露

<template>
  <div class="children">
    <h2>我是子組件</h2>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  setup(props, { expose }) {
    let counter = ref(0);
    const setCounter = (count: number) => {
      counter.value = count;
    };

    expose({
      setCounter,
    });
    return { counter };
  },
});
</script>

然后父組件通過ref綁定子組件之后,就可以調(diào)用子組件暴露出來的setCounter函數(shù)了

<template>
  <div class="parent">
    <Children  ref="childrenRef"></Children>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from "vue";
import Children from "./Children.vue";

export default defineComponent({
  components: {
    Children,
  },
  setup() {
    const childrenRef = ref(null);
    onMounted(() => {
      childrenRef.value.setCounter(2);
    });
    return { childrenRef };
  },
});
</script>

再來看一個例子
假如有這么一個需求惩淳,需要你將Children以插槽的方式傳進(jìn)Parent組件蕉毯,

<template>
  <div class="parent">
    <slot></slot>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  setup() {
    return {};
  },
});
</script>

并且Parent組件內(nèi)部要對插槽的內(nèi)容進(jìn)行校驗(yàn)乓搬,必須是Children組件。再創(chuàng)建一個test.vue

// test.vue
<template>
  <div>
    <Parent> 
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
    </Parent>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import Parent from "./components/Parent.vue";
import Children from "./components/Children.vue";

export default defineComponent({
  components: {
    Parent,
    Children,
  },
  setup() {
    return {};
  },
});
</script>

需求的意思就是Parent組件內(nèi)部要進(jìn)行校驗(yàn)代虾,總不可能將Parent內(nèi)部的直接子元素一一綁定ref吧进肯?這樣太過冗余,如果傳入了上百個Children組件呢棉磨?更麻煩了江掩。
所以還是要來說說setup的參數(shù)了,setup第二個參數(shù)context上有一個屬性slots,slots上又有一個方法default乘瓤,該方法的返回值就是一個插槽內(nèi)容的數(shù)組

<template>
  <div class="parent">
    <slot></slot>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  setup(props, context) {
    console.log(context);
    const defaults = context.slots.default()
    console.log(defaults);
    
    return {};
  },
});
</script>
info.png
Snipaste_2021-10-24_10-04-41.png

接下來在Parent.vue中導(dǎo)入Children組件环形,并在test.vue的Parent組件中添加一個div

    <Parent> 
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <Children></Children>
      <div>我是div</div>
    </Parent>

然后Parent組件內(nèi)部進(jìn)行判斷

<template>
  <div class="parent">
    <slot></slot>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import Children from "./Children.vue";

export default defineComponent({
  setup(props, context) {
    const defaults = context.slots.default();
    defaults.forEach((item) => {
      console.log(item.type === Children);
    });
    return {};
  },
});
</script>
Snipaste_2021-10-24_10-10-53.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市衙傀,隨后出現(xiàn)的幾起案子抬吟,更是在濱河造成了極大的恐慌,老刑警劉巖统抬,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件火本,死亡現(xiàn)場離奇詭異,居然都是意外死亡聪建,警方通過查閱死者的電腦和手機(jī)钙畔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來金麸,“玉大人刃鳄,你說我怎么就攤上這事∏睿” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵挪鹏,是天一觀的道長见秽。 經(jīng)常有香客問我,道長讨盒,這世上最難降的妖魔是什么解取? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮返顺,結(jié)果婚禮上禀苦,老公的妹妹穿的比我還像新娘。我一直安慰自己遂鹊,他們只是感情好振乏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秉扑,像睡著了一般慧邮。 火紅的嫁衣襯著肌膚如雪调限。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天误澳,我揣著相機(jī)與錄音耻矮,去河邊找鬼。 笑死忆谓,一個胖子當(dāng)著我的面吹牛裆装,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播倡缠,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼哨免,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了毡琉?” 一聲冷哼從身側(cè)響起铁瞒,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桅滋,沒想到半個月后慧耍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丐谋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年芍碧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片号俐。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡泌豆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情巫玻,我是刑警寧澤堕虹,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站贞远,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏笨忌。R本人自食惡果不足惜蓝仲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望官疲。 院中可真熱鬧袱结,春花似錦、人聲如沸途凫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽维费。三九已至棚饵,卻和暖如春煤裙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背噪漾。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工硼砰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欣硼。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓题翰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诈胜。 傳聞我的和親對象是個殘疾皇子豹障,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容