咱們先看一段代碼,功能很簡單,模板裏有一個按鈕,點擊按鈕,展現一個模態窗口。javascript
const app = Vue.createApp({ data() { return { show: false, }; }, methods: { handleShowModal() { this.show = true; }, }, template: ` <div class="box" id="box"> <button @click="handleShowModal">顯示模態窗口</button> <div class="modal" v-if="show">模態窗口</div> </div> ` }
模態窗口樣式以下:css
.box { position: absolute; width: 100px; height: 100px; background-color: cadetblue; } .modal { position: absolute; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.5); }
整個模態窗口呈絕對定位,left、right、top、bottom 所有給0,背景色爲黑色半透明。咱們指望的效果,應該點擊按鈕,模態窗口覆蓋整個頁面。html
如今咱們來運行下,咱們會發現,其實模態窗口只覆蓋了 #box
元素,由於 #box
自己就是絕對定位, 模態窗口元素是他的子節點,因此模態窗口只覆蓋了 #box
元素。vue
若是在沒有學習 teleport 以前,咱們會在根節點定義一個模態窗口,在業務組件裏去作調用。可是這樣的話,組件與模態窗口的邏輯就會產生割裂感。那有沒有什麼方法,可讓我模態窗口就寫在這個組件內,但真正呈如今頁面時,能夠動態插入到 元素上的,實際上是有的,咱們只要簡單的修改下 template模板,就能夠實現這個要求了。java
template: ` <div class="box"> <button @click="handleShowModal">顯示模態窗口</button> <teleport to="body"> <div class="modal">模態窗口</div> </teleport> </div> `
咱們用 teleport 元素將 modal 包裹起來,並定義屬性 to="body"
,運行頁面,咱們查看 dom 節點,就會發現 modal 元素已經追加到 body 底部了,效果以下。app
--body --#root vue根節點 --.modal 模態窗口
若是咱們想將 modal 節點傳送到其餘位置,也能夠這麼作。dom
<teleport to="#app"> <div class="modal">模態窗口</div> </teleport>
這段代碼就是將 modal 元素追加到 id=app 的元素內,有一點須要注意,我一直說的是追加元素
,假如說,原來 #app 內部已經存在其餘節點,那麼 modal 元素將追加到這些節點以後,有興趣能夠本身試一下。學習
其實使用在組件上和普通的 dom 元素並無什麼區別,組件中的節點將被渲染到指定的dom節點中(body或者指定ID)this
const app = Vue.createApp({ ... template: ` <div class="box" id="box"> <button @click="handleShowModal">顯示模態窗口</button> <teleport to="body"> <child-component :name="name"/> </teleport> </div> ` } app.component('child-component',{ props:['name'] template: `<div class='modal'>{{name}}</div>` })
即便被渲染到不一樣的節點,它仍和普通子組件同樣,接收父組件傳輸的數據,並無由於渲染節點改變而改變。code
<teleport to="#modals"> <div>A</div> </teleport> <teleport to="#modals"> <div>B</div> </teleport>
結果以下:
-- #modal -- A -- B
因此上面我一直強調,使用 teleport 是將包裹元素追加到指定節點,因此上面兩個 teleport 將依次追加到 #modal 上。
teleport多應用於邏輯屬於該組件,而從技術角度講,卻要把它移動到其餘節點(body或者指定ID的元素) 裏。最多見的場景就是建立一個包含全屏模式的組件,邏輯存在於組件內,可是基於css樣式,卻要把他移動到 body 元素上。