VueJs中如何使用Teleport及組件嵌套層次結(jié)構(gòu)詳解
正文
在DOM
結(jié)構(gòu)相對比較復(fù)雜,層級嵌套比較深的組件內(nèi),需要根據(jù)相對應(yīng)的模塊業(yè)務(wù)處理一些邏輯,該邏輯屬于當(dāng)前組件
但是從整個頁面應(yīng)用的視圖上看,它在DOM
中應(yīng)該被渲染在整個vue
應(yīng)用外部的其他地方,不能影響組件的結(jié)構(gòu)
比較常見的應(yīng)用場景:就是全屏的模態(tài)框,控制元素的位置,也是可以處理的,但是比較麻煩
在理想情況下,我們希望在具體的組件中,給元素綁定的事件,與具體要控制的DOM
元素結(jié)構(gòu)在同一個組件中,具體的位置處,保持一定的相關(guān)聯(lián)性
而不用特意的把一些DOM
結(jié)構(gòu)給分離出去,然而,在同一組件中,觸發(fā)模態(tài)框的按鈕和模態(tài)框本身在同一組件中
因?yàn)樗麄兌寂c組件的開關(guān)狀態(tài)有相關(guān)聯(lián),模態(tài)框與按鈕一起渲染在應(yīng)用DOM
結(jié)構(gòu)很深的地方,會導(dǎo)致模態(tài)框的css布局位置非常難控制
鑒于這樣的場景和困難,Vue
官方提供了一個Teleport
組件,很好的可以解決這個問題,讓開發(fā)者不需要顧慮DOM
結(jié)構(gòu)的問題
01-組件套組件層次結(jié)構(gòu)很深時
比如:現(xiàn)在有兩個組件,父組件,子組件,在后代組件內(nèi),添加一個按鈕,彈出一個模態(tài)框,讓它在頁面垂直水平居中顯示
如下所示,父組件如下所示App.vue
<template> <div class="App"> 我是父組件 <Child /> </div> </template> <script setup> import Child from "./Child.vue" </script> <style> .App { width: 400px; height: 400px; background:red; } </style>
如下是Child
組件,示例代碼如下所示Child.vue
,我們需要在孫(后代)組件,添加一個按鈕,點(diǎn)擊按鈕,彈出一個彈框,水平垂直居中顯示在頁面中央
<template> <div class="child"> <p>我是子組件</p> <button @click="isModel=true">打開模態(tài)框</button> <div class="mask-dialog" v-if="isModel"> <div class="box"> <h2>我是標(biāo)題</h2> <div>我是彈框內(nèi)容</div> <div> <button @click="isModel=false">關(guān)閉</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
按鈕來觸發(fā)打開當(dāng)前組件的模態(tài)框,里面存在著控制彈框的顯示和隱藏的邏輯,當(dāng)嵌套的組件比較深,復(fù)雜時
如果父級元素存在定位,那在控制子元素的位置時,用css
的transform
或者position:absolute
,參照對象的變更,會破壞布局結(jié)構(gòu),會出現(xiàn)一些css
樣式
控制的問題,解決起來會非常的痛苦
那這個Teleport
組件就是為了解決這類問題,可以將指定的DOM
結(jié)構(gòu)片段,獨(dú)立于到組件外面去,不受當(dāng)前組件布局結(jié)構(gòu)的影響
經(jīng)過Teleport
的修改后
<template> <div class="child"> <p>我是子組件</p> <button @click="isModel=true">打開模態(tài)框</button> <Teleport to="body"> <div class="mask-dialog" v-if="isModel"> <div class="box"> <h2>我是標(biāo)題1</h2> <div>我是彈框內(nèi)容</div> <div> <button @click="isModel=false">關(guān)閉</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
來指定傳送的目標(biāo)。to
的值可以是一個 CSS
選擇器字符串,或id
,也可以是一個 DOM
元素對象。這段代碼的作用就是告訴 Vue
把以下模板片段傳送到 body
標(biāo)簽下
<Teleport to="#some-id">html結(jié)構(gòu)代碼</Teleport> <Teleport to=".some-class">html結(jié)構(gòu)代碼</Teleport> <Teleport to="body">html結(jié)構(gòu)代碼</Teleport> <Teleport to="html">html結(jié)構(gòu)代碼</Teleport>
02-Teleport組件
它是Vue
官方提供的一個內(nèi)置組件,它可以將一個組件內(nèi)部的一部分模板“傳送”到該組件的 DOM
結(jié)構(gòu)外層的位置去 也就是一種能夠?qū)⑽覀兊慕M件html
結(jié)構(gòu)移動到指定位置的技術(shù)
<teleport to="移動到指定的位置,可以是html,body,或id,class"> 里面是Html結(jié)構(gòu)模板內(nèi)容 </teleport>
注意
<Teleport>
掛載時,傳送的 to
目標(biāo)必須已經(jīng)存在于DOM
中。理想情況下,這應(yīng)該是整個 Vue
應(yīng)用 DOM
樹外部的一個元素。如果目標(biāo)元素也是由 Vue
渲染的,你需要確保在掛載 <Teleport>
之前先掛載該元素
這個teleport
將指定的模板html
,放置到頁面當(dāng)中指定的位置處,它是有條件的,不是可以任意傳送的
在安裝組件之前,目標(biāo)元素必須存在,即,目標(biāo)不能由組件本身呈現(xiàn),理想情況下應(yīng)該位于整個Vue
組件樹之外。
如下代碼是不行的
<template> <div class="header"> <Teleport to=".content"> <div>我是頭部的內(nèi)容</div> </Teleport> </div> <div class="footer"> 底部內(nèi)容 <div class="content"></div> </div> </template> <script setup> </script> <style lang="less"> h1 { color: red; } </style>
03-需要知道的
teleport
只是改變了渲染的 DOM
結(jié)構(gòu),它不會影響組件間的邏輯關(guān)系。也就是說,如果 <Teleport>
包含了一個組件,那么該組件始終和這個使用了 <teleport>
的組件保持邏輯上的父子關(guān)系。傳入的 props
和觸發(fā)的事件也會照常工作。
這也意味著來自父組件的注入也會按預(yù)期工作,子組件將在 Vue Devtools
中嵌套在父級組件下面,而不是放在實(shí)際內(nèi)容移動到的地方
位置移動了,提現(xiàn)在結(jié)構(gòu)模板上,但是數(shù)據(jù)邏輯依舊存在關(guān)聯(lián)的
04-如何禁用 Teleport
在某些場景下可能需要視情況禁用 <Teleport>
。舉例來說,我們想要在桌面端將一個組件當(dāng)做浮層來渲染,但在移動端則當(dāng)作行內(nèi)組件。我們可以通過對 <Teleport>
動態(tài)地傳入一個 disabled prop
來處理這兩種不同情況
<Teleport :disabled="isMobile"> ... </Teleport>
這里的 isMobile
狀態(tài)可以根據(jù) CSS media query
的不同結(jié)果動態(tài)地更新
05-多個 Teleport 共享目標(biāo)時
一個可重用的模態(tài)框組件可能同時存在多個實(shí)例。對于此類場景,多個 <Teleport>
組件可以將其內(nèi)容掛載在同一個目標(biāo)元素上,而順序就是簡單的順次追加,后掛載的將排在目標(biāo)元素下更后面的位置上
比如下面這樣的用例
<Teleport to=".content"> <div>A</div> </Teleport> <Teleport to=".content"> <div>B</div> </Teleport>
渲染的結(jié)果為
<div class="content"> <div>A</div> <div>B</div> </div>
總結(jié)
這個teleport
組件在實(shí)際開發(fā)中還是很實(shí)用的,能夠解決當(dāng)組件嵌套層級很深,而后代組件中的模板,想要脫離當(dāng)前組件結(jié)構(gòu),解決css
布局層面的干擾,那就可以用這個teleport
組件
以上就是VueJs中如何使用Teleport及組件嵌套層次結(jié)構(gòu)詳解的詳細(xì)內(nèi)容,更多關(guān)于VueJs使用Teleport組件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue的圖片需要用require的方式進(jìn)行引入問題
這篇文章主要介紹了vue的圖片需要用require的方式進(jìn)行引入問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03記一次vue-webpack項(xiàng)目優(yōu)化實(shí)踐詳解
這篇文章主要介紹了記一次vue-webpack項(xiàng)目優(yōu)化實(shí)踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-02-02Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹和選人功能
這篇文章主要介紹了Vue.js遞歸組件實(shí)現(xiàn)組織架構(gòu)樹和選人功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07在VUE中使用lodash的debounce和throttle操作
這篇文章主要介紹了在VUE中使用lodash的debounce和throttle操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11vue項(xiàng)目國際化vue-i18n的安裝使用教程
最近接觸學(xué)習(xí)Vue.js框架結(jié)合Element-ui組件開發(fā)項(xiàng)目。由于最近需要實(shí)現(xiàn)國際化功能,所以下面這篇文章主要介紹了vue項(xiàng)目國際化vue-i18n的使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2018-03-03