W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Vue 鼓勵(lì)我們通過(guò)將 UI 和相關(guān)行為封裝到組件中來(lái)構(gòu)建 UI。我們可以將它們嵌套在另一個(gè)內(nèi)部,以構(gòu)建一個(gè)組成應(yīng)用程序 UI 的樹。
然而,有時(shí)組件模板的一部分邏輯上屬于該組件,而從技術(shù)角度來(lái)看,最好將模板的這一部分移動(dòng)到 DOM 中 Vue app 之外的其他位置。
一個(gè)常見的場(chǎng)景是創(chuàng)建一個(gè)包含全屏模式的組件。在大多數(shù)情況下,你希望模態(tài)框的邏輯存在于組件中,但是模態(tài)框的快速定位就很難通過(guò) CSS 來(lái)解決,或者需要更改組件組合。
考慮下面的 HTML 結(jié)構(gòu)。
<body>
<div style="position: relative;">
<h3>Tooltips with Vue 3 Teleport</h3>
<div>
<modal-button></modal-button>
</div>
</div>
</body>
讓我們來(lái)看看 modal-button
組件:
該組件將有一個(gè) button
元素來(lái)觸發(fā)模態(tài)的打開,以及一個(gè)具有類 .modal
的 div
元素,它將包含模態(tài)的內(nèi)容和一個(gè)用于自關(guān)閉的按鈕。
const app = Vue.createApp({});
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal!
</button>
<div v-if="modalOpen" class="modal">
<div>
I'm a modal!
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
`,
data() {
return {
modalOpen: false
}
}
})
當(dāng)在初始的 HTML 結(jié)構(gòu)中使用這個(gè)組件時(shí),我們可以看到一個(gè)問(wèn)題——模態(tài)是在深度嵌套的 div
中渲染的,而模態(tài)的 position:absolute
以父級(jí)相對(duì)定位的 div
作為引用。
Teleport 提供了一種干凈的方法,允許我們控制在 DOM 中哪個(gè)父節(jié)點(diǎn)下呈現(xiàn) HTML,而不必求助于全局狀態(tài)或?qū)⑵洳鸱譃閮蓚€(gè)組件。
讓我們修改 modal-button
以使用 <teleport>
,并告訴 Vue “Teleport 這個(gè) HTML 到該‘body’標(biāo)簽”。
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
因此,一旦我們單擊按鈕打開模式,Vue 將正確地將模態(tài)內(nèi)容渲染為 body
標(biāo)簽的子級(jí)。
如果 <teleport>
包含 Vue 組件,則它仍將是 <teleport>
父組件的邏輯子組件:
const app = Vue.createApp({
template: `
<h1>Root instance</h1>
<parent-component />
`
})
app.component('parent-component', {
template: `
<h2>This is a parent component</h2>
<teleport to="#endofbody">
<child-component name="John" />
</teleport>
`
})
app.component('child-component', {
props: ['name'],
template: `
<div>Hello, {{ name }}</div>
`
})
在這種情況下,即使在不同的地方渲染 child-component
,它仍將是 parent-component
的子級(jí),并將從中接收 name
prop。
這也意味著來(lái)自父組件的注入按預(yù)期工作,并且子組件將嵌套在 Vue Devtools 中的父組件之下,而不是放在實(shí)際內(nèi)容移動(dòng)到的位置。
一個(gè)常見的用例場(chǎng)景是一個(gè)可重用的 <Modal>
組件,它可能同時(shí)有多個(gè)實(shí)例處于活動(dòng)狀態(tài)。對(duì)于這種情況,多個(gè) <teleport>
組件可以將其內(nèi)容掛載到同一個(gè)目標(biāo)元素。順序?qū)⑹且粋€(gè)簡(jiǎn)單的追加——稍后掛載將位于目標(biāo)元素中較早的掛載之后。
<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals">
<div>B</div>
</teleport>
<!-- result-->
<div id="modals">
<div>A</div>
<div>B</div>
</div>
你可以在 API 參考 查看 teleport
組件。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: