对vant ui 中的toast进行二次封装
Toast组件
Toast.vue
<template>
<van-toast class="xd-toast" v-model:show="visible" :position="'top'" style="padding: 0" :duration="durationTime">
<template #message>
<div class="message-content">
<SvgIcon :name="`toast-${iconName}`" :color="typeObj[iconName]"></SvgIcon>
<span>{{ message }}</span>
</div>
</template>
</van-toast>
</template>
<script setup lang="ts">
interface Options {
msg: string
type?: string
duration?: number
}
const typeObj: any = {
info: '#FF6F66',
success: '#49D74E'
}
const visible = ref(false)
const message = ref('')
const iconName = ref('info')
const durationTime = ref(2000)
// 如有需求,可以自定义入参
const show = ({ msg, type, duration }: Options) => {
visible.value = true
message.value = msg
iconName.value = formatType(type || 'info')
durationTime.value = duration || 2000
console.log('......', visible.value)
}
const formatType = (type: string): string => {
return typeObj[type] ? type : 'info'
}
defineExpose({
show
})
</script>
<style lang="scss" scoped>
.xd-toast {
z-index: 2500;
.message-content {
display: flex;
align-items: center;
padding: 14px 50px;
font-size: 24px;
color: #fff;
line-height: 28px;
.svg-icon {
margin-right: 20px;
}
}
}
</style>
index.ts
import XdToast from './Toast.vue'
import { render, createVNode } from 'vue'
const instances: any[] = []
let node: HTMLElement | null = null
const duration = 2000
let timer: any = null
const onDestroy = () => {
if (node && instances.length) {
document.body.removeChild(node)
instances.pop()
}
}
export default function Toast(options: any) {
if (instances.length) return
if (timer) {
clearInterval(timer)
}
const parentNode = document.createElement('div')
const id = 'xd-toast'
// 这里传入的props在组件中通过 Props接收
const vnode = createVNode(XdToast, { id, props: { ...options }, zIndex: 2500 })
render(vnode, parentNode)
node = document.body.appendChild(parentNode)
const instance = vnode.component!
instances.push(instance)
if (instance) {
// 调用组件对外暴露的show方法
instance.exposed?.show(options)
timer = setTimeout(onDestroy, (options.duration || duration) + 500)
}
}
- 创建toast实例时,参数可以通过Props接受,也可以通过调用组件方法,通过入参接受。
- 创建时需要考虑多个toast同时创建的场景
- 实例结束之后需要及时销毁,不然元素节点会一直增加