vue3.0新特性teleport是啥,用起來真香(開闊視野!)
前言
在vue2.0時(shí)代,我們經(jīng)常會(huì)有這樣的需求,寫代碼邏輯的時(shí)候希望將組件寫在某個(gè)模板之下,因?yàn)檫@樣我們很好的使用組件內(nèi)部的狀態(tài)數(shù)據(jù),控制組件的展示形態(tài)。但是從技術(shù)的角度上我們又希望將這段代碼移到DOM中Vue app之外的其他位置。
舉個(gè)簡(jiǎn)單的例子,我們?cè)谑褂?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;">modal組件的時(shí)候,我們將它放在了我們的模板template里面,但是由于modal組件希望位于頁面的最上方,這時(shí)候我們將modal組件掛載在body上面是最好控制的,我們能夠很好的通過zIndex來控制modal的位置,當(dāng)他嵌套在templat里面的時(shí)候就不那么容易了。
vue2.0中的實(shí)現(xiàn)
vue2.0中我在寫這個(gè)組件的時(shí)候是通過手動(dòng)的形式來進(jìn)行掛載的,我寫了一個(gè)vue指令來進(jìn)行這個(gè)操作,幫助我將modal組件掛載到body上面去,專這樣也能夠很好的通過控制zIndex來控制modal的展示。
function?insert(el)?{
??const?parent?=?el.parentNode;
??if?(parent?&&?parent?!==?document.body)?{
??????parent.removeChild(el);
??????document.body.appendChild(el);
??}
}
export?default?(typeof?window?!==?'undefined'???{
??inserted(el,?{?value?})?{
??????if?(value)?{
??????????insert(el);
??????}
??},
??componentUpdated(el,?{?value?})?{
??????if?(value)?{
??????????insert(el);
??????}
??},
}?:?{});
上面的代碼其實(shí)就是簡(jiǎn)單的將modal從他原始掛載的父節(jié)點(diǎn)移除,然后掛載到body上去,通過手動(dòng)的形式來重新掛載,能夠很好的解決這種問題,當(dāng)然上面只是簡(jiǎn)單的邏輯,如果需要考慮卸載等其他邏輯代碼還得增加。
??<div?class="modal"?v-to-body="show"?v-if="show">
????<div?class="modal-mask"?@click="close">div>
????<slot>slot>
??div>
</template>
說實(shí)話vue2.0中的實(shí)現(xiàn)其實(shí)是沒啥問題的,只是不是很優(yōu)雅,需要額外的代碼控制,所以vue3.0中直接帶來了Teleport-任意傳送門
具體代碼參考vue2.0-modal:?https://codesandbox.io/s/vue20-modal-sc1rq
什么是Teleport
Teleport能夠直接幫助我們將組件渲染后頁面中的任意地方,只要我們指定了渲染的目標(biāo)對(duì)象。Teleport使用起來非常簡(jiǎn)單。
??<teleport?to="body"?class="modal"?v-if="show">
????<div?class="modal-mask"?@click="close">div>
????<slot>slot>
??teleport>
</template>
上面的代碼我們就能夠很簡(jiǎn)單的實(shí)現(xiàn)之前vue2.0所實(shí)現(xiàn)的功能。
具體代碼參考vue3.0-modal:?https://codesandbox.io/s/vue3-modal-x2lud
注意點(diǎn)
與 Vue components 一起使用
在這種情況下,即使在不同的地方渲染child-component,它仍將是parent-component的子級(jí),并將從中接收name prop。
這也意味著來自父組件的注入按預(yù)期工作,并且子組件將嵌套在Vue Devtools中的父組件之下,而不是放在實(shí)際內(nèi)容移動(dòng)到的位置。
const?app?=?Vue.createApp({
??template:?`
????Root?instance
????
??`
})
app.component('parent-component',?{
??template:?`
????This?is?a?parent?component
????
??????
????
??`
})
app.component('child-component',?{
??props:?['name'],
??template:?`
????Hello,?{{?name?}}
??`
})
在同一目標(biāo)上使用多個(gè)teleport
當(dāng)我們將多個(gè)teleport送到同一位置時(shí)會(huì)發(fā)生什么?
"#modals">
??<div>Adiv>
</teleport>
??Bdiv>
</teleport>
??Adiv>
??<div>Bdiv>
</div>
我們可以看到對(duì)于這種情況,多個(gè)teleport組件可以將其內(nèi)容掛載到同一個(gè)目標(biāo)元素。順序?qū)⑹且粋€(gè)簡(jiǎn)單的追加——稍后掛載將位于目標(biāo)元素中較早的掛載之后。
總結(jié)
一句話來描述Teleport就是一種將代碼組織邏輯依舊放在組件中,這樣我們能夠使用組件內(nèi)部的數(shù)據(jù)狀態(tài),控制組件展示的形式,但是最后渲染的地方可以是任意的,而不是局限于組件內(nèi)部
-?END -
點(diǎn)贊 + 在看 + 分享,一鍵三連,幸福滿滿!
最后
如果你覺得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:
點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)
歡迎加我微信「qianyu443033099」拉你進(jìn)技術(shù)群,長(zhǎng)期交流學(xué)習(xí)...
關(guān)注公眾號(hào)「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。

點(diǎn)個(gè)在看支持我吧,轉(zhuǎn)發(fā)就更好了
瀏覽
1 