Vue3值得注意的新特性之——teleport
前提
Vue鼓勵(lì)我們通過(guò)將UI和相關(guān)行為封裝到組件中來(lái)構(gòu)建UI。我們可以將它們嵌套在另一個(gè)內(nèi)部,來(lái)構(gòu)建一個(gè)組成應(yīng)用程序UI樹(shù)。
然而,有時(shí)組件模板的一部分邏輯上屬于該組件,而從技術(shù)角度來(lái)看,最好將模板的這一部分移動(dòng)到DOM中Vue app之外的其他位置。
Teleport提供了一種干凈的方法,允許我們控制在DOM中哪個(gè)父節(jié)點(diǎn)下渲染HTML,而不必求助于全局狀態(tài)或?qū)⑵洳鸱譃閮蓚€(gè)組件。
- 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 compoents一起使用
如果<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-compoents,它仍將是parent-component的子集,并將從中接受name prop。
這也意味著來(lái)自父組件的注入按預(yù)期工作,并且子組件將嵌套在Vue Devtools中的父組件之下,部署放在實(shí)際內(nèi)容移動(dòng)到的位置。
在同一目標(biāo)上使用多個(gè)teleport
一個(gè)常見(jiàn)的用例場(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>
使用
to:String。需要prop,必須是有效的查詢選擇器或HTMLElement(如果在瀏覽器環(huán)境中使用)。指定將在其移動(dòng)<teleport>內(nèi)容的目標(biāo)元素。
- <!-- 正確 -->
- <teleport to="#some-id" />
- <teleport to=".some-class" />
- <teleport to="[data-teleport]" />
- <!-- 錯(cuò)誤 -->
- <teleport to="h1" />
- <teleport to="some-string" />
disabled: boolean。此可選屬性可用于禁用<teleport>的功能,這意味著其插槽內(nèi)容不會(huì)移動(dòng)到任何位置。而是在您在周?chē)附M件中指定了<teleport>的位置渲染。
- <teleport to="#popup" :disabled="displayVideoInline">
- <video src="./my-movie.mp4">
- </teleport>
值得注意的是,這將移動(dòng)實(shí)際的DOM節(jié)點(diǎn),而不是被銷(xiāo)毀和重新創(chuàng)建,而且它還將保持
任何組件實(shí)例的活動(dòng)狀態(tài)。所有有狀態(tài)的HTML元素(即播放的視頻)都將保持其狀態(tài)。