這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
在DOM結構相對比較復雜,層級嵌套比較深的組件內,需要根據相對應的模塊業務處理一些邏輯,該邏輯屬于當前組件
但是從整個頁面應用的視圖上看,它在DOM中應該被渲染在整個vue應用外部的其他地方,不能影響組件的結構
比較常見的應用場景:就是全屏的模態框,控制元素的位置,也是可以處理的,但是比較麻煩
在理想情況下,我們希望在具體的組件中,給元素系結的事件,與具體要控制的DOM元素結構在同一個組件中,具體的位置處,保持一定的相關聯性
而不用特意的把一些DOM結構給分離出去,然而,在同一組件中,觸發模態框的按鈕和模態框本身在同一組件中
因為他們都與組件的開關狀態有相關聯,模態框與按鈕一起渲染在應用DOM結構很深的地方,會導致模態框的css布局位置非常難控制
鑒于這樣的場景和困難,Vue官方提供了一個Teleport組件,很好的可以解決這個問題,讓開發者不需要顧慮DOM結構的問題
01-組件套組件層次結構很深時
比如:現在有兩個組件,父組件,子組件,在后代組件內,添加一個按鈕,彈出一個模態框,讓它在頁面垂直水平居中顯示
如下所示,父組件如下所示App.vue
<template>
<div >
我是父組件
<Child />
</div>
</template>
<script setup>
import Child from "./Child.vue"
</script>
<style>
.App {
width: 400px;
height: 400px;
background:red;
}
</style>
如下是Child組件,示例代碼如下所示Child.vue,我們需要在孫(后代)組件,添加一個按鈕,點擊按鈕,彈出一個彈框,水平垂直居中顯示在頁面中央
<template>
<div >
<p>我是子組件</p>
<button @click="isModel=true">打開模態框</button>
<div v-if="isModel">
<div >
<h2>我是標題</h2>
<div>我是彈框內容</div>
<div>
<button @click="isModel=false">關閉</button>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
let isModel = ref(false);
</script>
<style>
.child {
width: 300px;
height:300px;
background:green;
}
/**灰色遮罩層 */
.mask-dialog {
width: 100%;
height:100%;
position:absolute;
left:0;
top:0;
background:rgba(0,0,0,0.5)
}
.box {
width: 200px;
height:200px;
position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%);
background:pink;
text-align:center;
}
</style>
上面的子組件中有一個button按鈕來觸發打開當前組件的模態框,里面存在著控制彈框的顯示和隱藏的邏輯,當嵌套的組件比較深,復雜時
如果父級元素存在定位,那在控制子元素的位置時,用css的transform或者position:absolute,參照物件的變更,會破壞布局結構,會出現一些css樣式
控制的問題,解決起來會非常的痛苦
那這個Teleport組件就是為了解決這類問題,可以將指定的DOM結構片段,獨立于到組件外面去,不受當前組件布局結構的影響
經過Teleport的修改后
<template>
<div >
<p>我是子組件</p>
<button @click="isModel=true">打開模態框</button>
<Teleport to="body">
<div v-if="isModel">
<div >
<h2>我是標題1</h2>
<div>我是彈框內容</div>
<div>
<button @click="isModel=false">關閉</button>
</div>
</div>
</div>
</Teleport>
</div>
</template>
<script setup>
import { ref } from "vue";
let isModel = ref(false);
</script>
<style>
.child {
width: 300px;
height:300px;
background:green;
}
/**灰色遮罩層 */
.mask-dialog {
width: 100%;
height:100%;
position:absolute;
left:0;
top:0;
background:rgba(0,0,0,0.5)
}
.box {
width: 200px;
height:200px;
position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%);
background:pink;
text-align:center;
}
</style>
<Teleport>接收一個 to prop 來指定傳送的目標,to 的值可以是一個 CSS 選擇器字串,或id,也可以是一個 DOM 元素物件,這段代碼的作用就是告訴 Vue把以下模板片段傳送到 body 標簽下
<Teleport to="#some-id">html結構代碼</Teleport> <Teleport to=".some-class">html結構代碼</Teleport> <Teleport to="body">html結構代碼</Teleport> <Teleport to="html">html結構代碼</Teleport>
02-Teleport組件
它是Vue官方提供的一個內置組件,它可以將一個組件內部的一部分模板“傳送”到該組件的 DOM 結構外層的位置去 也就是一種能夠將我們的組件html結構移動到指定位置的技術
<teleport to="移動到指定的位置,可以是html,body,或id,class"> 里面是Html結構模板內容 </teleport>
注意
<Teleport> 掛載時,傳送的 to 目標必須已經存在于DOM中,理想情況下,這應該是整個 Vue 應用 DOM 樹外部的一個元素,如果目標元素也是由 Vue 渲染的,你需要確保在掛載 <Teleport> 之前先掛載該元素
這個teleport將指定的模板html,放置到頁面當中指定的位置處,它是有條件的,不是可以任意傳送的
在安裝組件之前,目標元素必須存在,即,目標不能由組件本身呈現,理想情況下應該位于整個Vue組件樹之外,
如下代碼是不行的
<template>
<div >
<Teleport to=".content">
<div>我是頭部的內容</div>
</Teleport>
</div>
<div >
底部內容
<div ></div>
</div>
</template>
<script setup>
</script>
<style lang="less">
h1 {
color: red;
}
</style>
03-需要知道的
teleport只是改變了渲染的 DOM 結構,它不會影響組件間的邏輯關系,也就是說,如果 <Teleport> 包含了一個組件,那么該組件始終和這個使用了 <teleport> 的組件保持邏輯上的父子關系,傳入的 props 和觸發的事件也會照常作業,
這也意味著來自父組件的注入也會按預期作業,子組件將在 Vue Devtools 中嵌套在父級組件下面,而不是放在實際內容移動到的地方
位置移動了,提現在結構模板上,但是資料邏輯依舊存在關聯的
04-如何禁用 Teleport
在某些場景下可能需要視情況禁用 <Teleport>,舉例來說,我們想要在桌面端將一個組件當做浮層來渲染,但在移動端則當作行內組件,我們可以通過對 <Teleport> 動態地傳入一個 disabled prop 來處理這兩種不同情況
<Teleport :disabled="isMobile"> ... </Teleport>
05-多個 Teleport 共享目標時
一個可重用的模態框組件可能同時存在多個實體,對于此類場景,多個 <Teleport> 組件可以將其內容掛載在同一個目標元素上,而順序就是簡單的順次追加,后掛載的將排在目標元素下更后面的位置上
比如下面這樣的用例
<Teleport to=".content"> <div>A</div> </Teleport> <Teleport to=".content"> <div>B</div> </Teleport>
渲染的結果為
<div > <div>A</div> <div>B</div> </div>
總結
這個teleport組件在實際開發中還是很實用的,能夠解決當組件嵌套層級很深,而后代組件中的模板,想要脫離當前組件結構,解決css布局層面的干擾,那就可以用這個teleport組件
本文轉載于:
https://juejin.cn/post/7217731723509547069
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/549455.html
標籤:其他

