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">&times;</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组件的资料请关注其它相关文章!

以上是 vue基于Teleport实现Modal组件 的全部内容, 来源链接: utcz.com/p/239258.html

回到顶部