Vue3中內(nèi)置組件Teleport的基本使用與典型案例
1. 基本概念
1.1 簡(jiǎn)單理解
不管是 Vue2 還是 Vue3 中都有內(nèi)置組件的存在,如 component 內(nèi)置組件、transition 內(nèi)置組件等等。內(nèi)置組件就是官方給我們封裝的全局組件,我們直接拿來(lái)用就可以了。
在 Vue3 中新增了 Teleport 內(nèi)置組件,先來(lái)看下官方文檔是怎么解釋的。
<Teleport> 是一個(gè)內(nèi)置組件,它可以將一個(gè)組件內(nèi)部的一部分模板“傳送”到該組件的 DOM 結(jié)構(gòu)外層的位置去。
通俗解釋:
teleport 是一個(gè)內(nèi)置組件,我們都知道 HTML 是由層級(jí)關(guān)系的,Vue3 中的組件也是有層級(jí)關(guān)系的。
假如在父組件中引用了一個(gè)子組件,那么渲染成頁(yè)面后這個(gè)子組件 HTML 也是必然被父組件 HTML 包含的。
但是如果把子組件放置到了 teleport 組件中,那么我們就可以指定該子組件渲染到父組件之外的其它 DOM 節(jié)點(diǎn)下,比如 body 或者其它的 DOM 等等。這就有點(diǎn)類似與“傳送”了。
1.2 典型案例
我們使用 Vue 的 UI 組件庫(kù)的時(shí)候,經(jīng)常會(huì)用到模態(tài)框這個(gè)組件。如:使用 Element-plus 的模態(tài)框。
<template> <el-button @click="dialogVisible = true">打開(kāi)彈窗</el-button> <el-dialog v-model="dialogVisible" append-to-body title="我是彈窗" width="30%"> </el-dialog> </template> <script> import { ref } from 'vue'; export default { setup(){ const dialogVisible = ref(false); return { dialogVisible } } } </script>
上段代碼中在 App.vue 組件里面引用了 Element-plus 的彈窗組件,并且添加了一個(gè) append-to-body 屬性。
可以看到雖然彈窗組件是寫(xiě)在 App.vue 組件里面的,但是渲染出來(lái)的結(jié)果卻是彈窗組件屬于 body 節(jié)點(diǎn),這是因?yàn)槔昧?Element-plus 中彈窗的 append-to-body 屬性,我們把該屬性去掉再看看什么結(jié)果:
可以看到彈窗組件又乖乖的跑到了 App.vue 組件下面。
為何要這樣做?
很簡(jiǎn)單,假如有非常多的彈窗,那么如何管理它們的 z-index 呢,也就是同時(shí)彈窗時(shí)的層級(jí)關(guān)系,如果每個(gè)彈窗都在各自的父組件中,那么我們是沒(méi)法控制的,所有有必要把它們都擰出來(lái),放在同一個(gè)父元素下面,這樣就可以方便的設(shè)置層級(jí)關(guān)系了。
這和 teleport 組件有什么關(guān)系嗎?有很大的關(guān)系,上面彈窗的 append-to-body 屬性效果是 Element 給我們做的,要是我們想自己實(shí)現(xiàn)這樣的效果,該怎么辦呢?我們就可以使用內(nèi)置組件 teleport 了。
2. 基礎(chǔ)使用
2.1 傳送 DOM 節(jié)點(diǎn)
<template> <div class="app"> App組件 <Teleport to="body"> <div>我是被 teleport 包裹的元素</div> </Teleport> </div> </template>
從上圖可以看出,Teleport 包裹的元素雖然是屬于 app.vue 組件,但是渲染過(guò)后它卻被渲染在了 body 這個(gè) dom 元素下面了。
這都得歸功于 Teleport 得傳送功能,它的用法很簡(jiǎn)單,語(yǔ)法代碼如下:
其中 to 就是“傳送”的目的地了,即需要把包裹的內(nèi)容傳送到何處去。
<Teleport to="body"> </Teleport> to 允許接收值: 期望接收一個(gè) CSS 選擇器字符串或者一個(gè)真實(shí)的 DOM 節(jié)點(diǎn)。 提示: <Teleport> 掛載時(shí),傳送的 to 目標(biāo)必須已經(jīng)存在于 DOM 中。理想情況下,這應(yīng)該是整個(gè) Vue 應(yīng)用 DOM 樹(shù)外部的一個(gè)元素。 如果目標(biāo)元素也是由 Vue 渲染的,你需要確保在掛載 <Teleport> 之前先掛載該元素。
2.2 傳送組件
< Teleport > 只改變了渲染的 DOM 結(jié)構(gòu),它不會(huì)影響組件間的邏輯關(guān)系。
也就是說(shuō),如果 < Teleport > 包含了一個(gè)組件,那么該組件始終和這個(gè)使用了 < teleport > 的組件保持邏輯上的父子關(guān)系。傳入的 props 和觸發(fā)的事件也會(huì)照常工作。
這也意味著來(lái)自父組件的注入也會(huì)按預(yù)期工作,子組件將在 Vue Devtools 中嵌套在父級(jí)組件下面,而不是放在實(shí)際內(nèi)容移動(dòng)到的地方。
// 父組件 <template> <div class="app"> <Teleport to="body"> <div>被 teleport 包裹的組件-- {{count}}</div> <ChildComponent v-model="count"/> </Teleport> </div> </template> <script> import { ref } from 'vue'; import ChildComponent from '@/components/childComponent'; export default { components:{ ChildComponent }, setup(){ const count = ref(100); return { count, } } } </script>
// 子組件 <template> 子組件:<input type="text" v-model.number="inputVal" @input="userInput"> </template> <script> import { ref, watch } from 'vue'; export default { props:{ modelValue:{ default:0, } }, setup(props,{emit}) { const inputVal = ref(null); const userInput = () => { emit('update:modelValue', inputVal.value) }; watch(props,(newVal,oldVal) => { inputVal.value = props.modelValue; },{immediate:true}) return { userInput, inputVal, } }, } </script>
2.3 禁用傳送功能
在某些場(chǎng)景下可能需要視情況禁用 < Teleport >,我們可以通過(guò)對(duì) < Teleport > 動(dòng)態(tài)地傳入一個(gè) disabled prop 來(lái)處理這兩種不同情況( disabled 屬性接收一個(gè) Boolean 值,true 代表不允許傳送,false 代表傳送)。
<template> <div class="app"> app組件 <Teleport to="body" :disabled="true"> <p>我是被 teleport 包裹的元素</p> <p>{{ message }}</p> </Teleport> </div> </template> <script> import { ref } from 'vue'; export default { setup(){ const message = ref('我是在 App 組件內(nèi)部'); return { message, } } } </script>
2.4 多個(gè)元素傳送給一個(gè)節(jié)點(diǎn)
多個(gè) < Teleport > 組件可以將其內(nèi)容掛載在同一個(gè)目標(biāo)元素上,而順序就是簡(jiǎn)單的順次追加,后掛載的將排在目標(biāo)元素下更后面的位置上。
<!-- index.html --> <body> <div id="app"></div> <div id="customDom"></div> </body>
<template> app組件 <Teleport to="#customDom"> <p>我是被 teleport 包裹的一號(hào)元素</p> </Teleport> <Teleport to="#customDom"> <p>我是被 teleport 包裹的二號(hào)元素</p> </Teleport> </template>
總結(jié)
到此這篇關(guān)于Vue3中內(nèi)置組件Teleport的基本使用與典型案例的文章就介紹到這了,更多相關(guān)Vue3內(nèi)置組件Teleport內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue如何實(shí)現(xiàn)點(diǎn)擊選中取消切換
這篇文章主要介紹了vue實(shí)現(xiàn)點(diǎn)擊選中取消切換,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05VSCode使React?Vue代碼調(diào)試變得更爽
這篇文章主要為大家介紹了VSCode使React?Vue代碼調(diào)試變得更爽的使用方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Vue-Router基礎(chǔ)學(xué)習(xí)筆記(小結(jié))
這篇文章主要介紹了Vue-Router基礎(chǔ)學(xué)習(xí)筆記(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10Vue如何實(shí)現(xiàn)響應(yīng)式系統(tǒng)
這篇文章給大家整理了關(guān)于Vue如何實(shí)現(xiàn)響應(yīng)式系統(tǒng)的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友可以參考學(xué)習(xí)下。2018-07-07移動(dòng)端底部導(dǎo)航固定配合vue-router實(shí)現(xiàn)組件切換功能
經(jīng)常遇到這樣的需求,移動(dòng)端中的導(dǎo)航并不是在頂部也不是在底部,而是在最底部且是固定的,當(dāng)我們點(diǎn)擊該導(dǎo)航項(xiàng)時(shí)會(huì)切換到對(duì)應(yīng)的組件。這篇文章主要介紹了移動(dòng)端底部導(dǎo)航固定配合vue-router實(shí)現(xiàn)組件切換功能,需要的朋友可以參考下2019-06-06Monaco?Editor開(kāi)發(fā)SQL代碼提示編輯器實(shí)例詳解
這篇文章主要為大家介紹了Monaco?Editor開(kāi)發(fā)SQL編輯器實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08