1.认识Teleport
vue3新增特性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>
6.git地址
后续添加
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!