vue基於Teleport實現Modal組件
1.認識Teleport
像我們如果寫Modal組件、Message組件、Loading組件這種全局式組件,沒有Teleport的話,將它們引入一個.vue文件中,則他們的HTML結構會被添加到組件模板中,這是不夠完美的。
- 沒有Teleport
- 有Teleport
下面就實戰介紹一下如何用Teleport開發Modal組件
2.Teleport的基本用法
Teleport的寫法十分簡單,隻需要用<Teleport></Teleport>將內容包裹,並用to指定將HTML掛到哪個父節點下,就可以啦。
<teleport to="#modal"> 內容 </teleport>
3.第一步優化
如果我們在代碼中將Teleport要掛載的DOM寫死,那麼每創建一個全局式組件,就需要有一個DOM節點,會越來越多,並且一直存在,這樣的寫法不是很優雅。比較好的解決方案就是:
- 在創建組件的時候,動態創建一個dom節點document.createElement(),
- 並添加到body中,document.body.appendChild(),
- 在組件卸載的時候銷毀這個dom document.body.removeChild(),
setup(){ const node = document.createElement('div') node.id = 'modal' document.body.appendChild(node) onUnmounted(() => { document.body.removeChild(node) }) }
4.第二步優化
如果我們後續還要添加Message組件,Loading組件等功能,同樣要用到Teleport,在每一個組件內部都寫這麼一段代碼,實在有點冗餘,vue3使我們能夠很方便的將邏輯功能提取出來,從而達到邏輯復用的目的。
我們在src-hooks文件夾下創建useDOMCreate.ts文件,來封裝這一塊邏輯
// hooks/useDOMCreate.ts import { onUnmounted } from 'vue' function useDOMCreate(nodeId:string):void { const node = document.createElement('div') node.id = nodeId document.body.appendChild(node) onUnmounted(() => { document.body.removeChild(node) }) } export default useDOMCreate
使用:
import useDOMCreate from '../hooks/useDOMCreate' setup(props, ctx) { useDOMCreate('modal') }
5.實現Modal組件
具體封裝Modal組件的細節這裡就不講啦,也沒有什麼復雜的邏輯。直接上代碼。
//Modal.vue <template> <teleport to="#modal"> <div class="modal d-block" tabindex="-1" v-if="isVisible"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">{{title}}</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true" @click="onClose">×</span> </button> </div> <div class="modal-body"> <slot></slot> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal" @click="onClose">取消</button> <button type="button" class="btn btn-primary" @click="onConfirm">確定</button> </div> </div> </div> </div> </teleport> </template> <script lang="ts"> import { defineComponent } from 'vue' import useDOMCreate from '../hooks/useDOMCreate' export default defineComponent({ name: 'Modal', emits: ['model-close', 'model-confirm'], props: { title: { type: String, default: '' }, isVisible: { type: Boolean, default: false } }, setup(props, ctx) { useDOMCreate('modal') const onClose = () => { ctx.emit('model-close') } const onConfirm = () => { ctx.emit('model-confirm') } return { onClose, onConfirm } } }) </script>
使用示例
<template> <div class="post-detail-page"> <button type="button" class="btn btn-danger" @click="handleDelete">刪除</button> <modal title='是否確認刪除?' :isVisible="modalVisible" @model-close="hanldeModalClose" @model-confirm="handleModalConfim"> <p>確認要刪除這篇文章嗎?</p> </modal> </div> </template> <script lang="ts"> import { defineComponent, ref } from 'vue' import Modal from '../components/Modal.vue' export default defineComponent({ name: 'post-detail', components: { Modal }, setup() { const modalVisible = ref(false) const handleDelete = () => { modalVisible.value = true } const hanldeModalClose = () => { modalVisible.value = false } const handleModalConfim = () => { modalVisible.value = false ... / /後續邏輯處理 } return { hanldeModalClose, handleModalConfim, handleDelete, modalVisible } } }) </script>
以上就是vue基於Teleport實現Modal組件的詳細內容,更多關於vue Teleport實現Modal組件的資料請關註WalkonNet其它相關文章!