)
Vue2通知提醒框Notification当前组件已优化重构具体功能文档请参考 在线预览可自定义设置以下属性通知提醒标题title优先级低于 Notification 中的 title类型string默认 undefined通知提醒内容description优先级低于 Notification 中的 description类型string默认 undefined自动关闭的延时时长duration单位 ms设置 null 时不自动关闭类型number | null默认 4500消息从顶部弹出时距离顶部的位置top单位 px类型number默认 24消息从底部弹出时距离底部的位置bottom单位 px类型number默认 24消息弹出位置placement优先级低于 Notification 中的 placement类型topLeft | topRight | bottomLeft | bottomRight默认 topRight其中调用时传入的 Notification 参数类型通知提醒标题title类型string默认 undefined通知提醒内容description类型string默认 undefined自定义图标icon类型VNode默认 undefined自定义类名class类型string默认 undefined自定义样式style类型CSSProperties默认 undefined自动关闭的延时时长duration单位 ms设置 null 时不自动关闭类型number | null默认 undefined通知提醒框弹出位置placement类型topLeft | topRight | bottomLeft | bottomRight默认 undefined关闭时的回调函数onClose类型Function默认 undefined调用时可选以下五个方法对应五种不同样式notification.value.open(data: Notification) // open 调用notification.value.info(data: Notification) // info调用notification.value.success(data: Notification) // success 调用notification.value.error(data: Notification) // error 调用notification.value.warning(data: Notification) // warning 调用效果如下图notification.value.open()调用notification.value.info()调用notification.value.success()调用notification.value.warning()调用notification.value.error()调用在线预览①创建通知提醒组件Notification.vue其中引入使用了以下组件函数使用requestAnimationFrame模拟实现setTimeout和setInterval获取依赖注入 useInjectscript setup langts import { ref, computed, watch, watchEffect, nextTick, onBeforeUnmount } from vue import type { VNode, CSSProperties } from vue import { rafTimeout, cancelRaf, useInject } from components/utils export interface Props { title?: string // 通知提醒标题优先级低于 Notification 中的 title description?: string // 通知提醒内容优先级低于 Notification 中的 description duration?: number | null // 自动关闭的延时时长单位 ms设置 null 时不自动关闭优先级低于 Notification 中的 duration top?: number // 消息从顶部弹出时距离顶部的位置单位 px bottom?: number // 消息从底部弹出时距离底部的位置单位 px placement?: topLeft | topRight | bottomLeft | bottomRight // 消息弹出位置优先级低于 Notification 中的 placement } const props withDefaults(definePropsProps(), { title: undefined, description: undefined, duration: 4500, top: 24, bottom: 24, placement: topRight }) export interface Notification { title?: string // 通知提醒标题 description?: string // 通知提醒内容 icon?: VNode // 自定义图标 class?: string // 自定义类名 style?: CSSProperties // 自定义样式 duration?: number | null // 自动关闭的延时时长单位 ms设置 null 时不自动关闭 placement?: topLeft | topRight | bottomLeft | bottomRight // 通知提醒弹出位置 onClose?: Function // 关闭时的回调函数 } const resetTimer ref() const hideIndex refnumber[]([]) const hideTimers refany[]([]) const notificationData refany[]([]) const closeDuration refnumber | null(null) // 自动关闭延时 const notificationPlace ref() // 弹出位置 const notificationRef ref() // notificationData 数组的 DOM 引用 const { colorPalettes } useInject(Notification) // 主题色注入 const emit defineEmits([close]) const topStyle computed(() { if ([topRight, topLeft].includes(notificationPlace.value)) { return { top: ${props.top}px } } return {} }) const bottomStyle computed(() { if ([bottomRight, bottomLeft].includes(notificationPlace.value)) { return { bottom: ${props.bottom}px } } return {} }) const clear computed(() { // 所有提示是否已经全部变为 false return hideIndex.value.length notificationData.value.length }) watch( clear, (to, from) { // 所有提示都消失后重置 if (!from to) { resetTimer.value rafTimeout(() { hideIndex.value [] notificationData.value [] }, 300) } }, { flush: post } ) watchEffect(() { notificationPlace.value props.placement }) onBeforeUnmount(() { hideTimers.value.forEach((rafId: any) { rafId cancelRaf(rafId) }) }) function onEnter(index: number) { stopAutoClose(index) } function onLeave(index: number) { if (!hideIndex.value.includes(index)) { autoClose(index) } } function stopAutoClose(index: number) { hideTimers.value[index] cancelRaf(hideTimers.value[index]) hideTimers.value[index] null } function autoClose(index: number) { if (closeDuration.value ! null) { hideTimers.value[index] rafTimeout(() { onClose(index) }, closeDuration.value) } } async function onClose(index: number) { notificationRef.value[index].style.maxHeight notificationRef.value[index].offsetHeight px await nextTick() hideIndex.value.push(index) hideTimers.value[index] null notificationData.value[index].onClose notificationData.value[index].onClose() emit(close) } function show() { resetTimer.value cancelRaf(resetTimer.value) hideTimers.value.push(null) const index notificationData.value.length - 1 const last notificationData.value[index] if (last.placement) { notificationPlace.value last.placement } if (last.duration ! null) { closeDuration.value last.duration || props.duration autoClose(index) } else { closeDuration.value null } } function open(notification: Notification) { notificationData.value.push({ ...notification, mode: open }) show() } function info(notification: Notification) { notificationData.value.push({ ...notification, mode: info }) show() } function success(notification: Notification) { notificationData.value.push({ ...notification, mode: success }) show() } function error(notification: Notification) { notificationData.value.push({ ...notification, mode: error }) show() } function warning(notification: Notification) { notificationData.value.push({ ...notification, mode: warning }) show() } defineExpose({ open, info, success, error, warning }) /script template div classnotification-wrap :classnotification-${notificationPlace} :style[ topStyle, bottomStyle, --notification-primary-color: ${colorPalettes[5]}; --notification-success-color: #52c41a; --notification-error-color: #ff4d4f; --notification-warning-color: #faad14; ] TransitionGroup :name[topRight, bottomRight].includes(notificationPlace) ? right : left div v-show!hideIndex.includes(index) refnotificationRef classnotification-container :class[icon-${notification.mode}, notification.class] :stylenotification.style v-for(notification, index) in notificationData :keyindex mouseenteronEnter(index) mouseleaveonLeave(index) component v-ifnotification.icon :isnotification.icon classicon-svg / svg v-else-ifnotification.mode info classicon-svg viewBox64 64 896 896 >script setup langts import Notification from ./Notification.vue import { ref, h } from vue import { CloudFilled, FireFilled } from ant-design/icons-vue const notification ref() function onOpen(description: string) { notification.value.open({ title: Notification Title, description }) // open 调用 } function onInfo(description: string) { notification.value.info({ title: Notification Title, description }) // info 调用 } function onSuccess(description: string) { notification.value.success({ title: Notification Title, description }) // success 调用 } function onWarning(description: string) { notification.value.warning({ title: Notification Title, description }) // warning 调用 } function onError(description: string) { notification.value.error({ title: Notification Title, description }) // error 调用 } function onInfoCustom(description: string) { notification.value.info({ title: Notification Title, icon: h(CloudFilled), description }) } function onOpenCustom(description: string) { notification.value.open({ title: Notification Title, icon: h(FireFilled, { style: color: gold }), description }) } function onClassCustom(description: string) { notification.value.open({ title: Notification Title, description, icon: h(FireFilled), class: custom-class }) } function onStyleCustom(description: string) { notification.value.open({ title: Notification Title, description, icon: h(CloudFilled), style: { width: 500px, color: #ff6900 } }) } function onOpenPlacement(placement: string) { notification.value.info({ title: Notification Title, description: This is the content of the notification., placement }) } function onCustomClose() { notification.value.info({ title: Notification Title, description: The notification will automatically turn off after 3 seconds., duration: 3000, onClose: () { console.log(custom notification closed) } }) } function onNeverAutoClose() { notification.value.info({ title: Notification Title, description: This notification will not automatically turn off., duration: null }) } function onClose() { // 通知提醒关闭时的回调函数 console.log(notification closed) } /script template div h1{{ $route.name }} {{ $route.meta.title }}/h1 h2 classmt30 mb10基本使用/h2 Button typeprimary clickonOpen(This is a normal notification)Open/Button h2 classmt30 mb10不同类型的通知提醒/h2 Space Button typeprimary clickonInfo(This is a normal notification)Info/Button Button typeprimary clickonSuccess(This is a success notification)Success/Button Button typeprimary clickonWarning(This is a warning notification)Warning/Button Button typeprimary clickonError(This is a error notification)Error/Button /Space h2 classmt30 mb10自定义图标/h2 Space Button typeprimary clickonInfoCustom(This is a custom icon notification)Custom Info Icon/Button Button typeprimary clickonOpenCustom(This is a custom icon notification)Custom Icon/Button /Space h2 classmt30 mb10自定义样式/h2 Space Button typeprimary clickonClassCustom(This is a custom class notification)Custom Class/Button Button typeprimary clickonStyleCustom(This is a custom style notification)Custom Style/Button /Space h2 classmt30 mb10弹出位置/h2 Space Button typeprimary clickonOpenPlacement(topLeft)topLeft/Button Button typeprimary clickonOpenPlacement(topRight)topRight/Button Button typeprimary clickonOpenPlacement(bottomLeft)bottomLeft/Button Button typeprimary clickonOpenPlacement(bottomRight)bottomRight/Button /Space h2 classmt30 mb10自定义关闭延时/h2 Space Button typeprimary clickonCustomCloseCustom Close/Button Button typeprimary clickonNeverAutoCloseNever Auto Close/Button /Space Notification refnotification closeonClose / /div /template style langless scoped :deep(.custom-class) { color: #d4380d; .notification-title { font-weight: 500; } } /style