您的位置:首页 > 游戏 > 游戏 > 广州app开发公司排行十强_互联网保险与传统保险的区别_客户管理软件_win10必做的优化

广州app开发公司排行十强_互联网保险与传统保险的区别_客户管理软件_win10必做的优化

2025/2/27 5:22:12 来源:https://blog.csdn.net/highlighters/article/details/145887155  浏览:    关键词:广州app开发公司排行十强_互联网保险与传统保险的区别_客户管理软件_win10必做的优化
广州app开发公司排行十强_互联网保险与传统保险的区别_客户管理软件_win10必做的优化

一、前言

在日常的前端项目开发中,我们时常需要使用到“消息提示”(以下简称“消息”)这个组件来帮助我们更好的给予用户提示,例如常见的“登录成功”、“操作成功”、“服务器异常”等等提示。
尽管市面上已经有一些组件库提供了这样的组件,例如国产的Element-Plus(如下图)。但他们还是有一个缺点,即如果我仅仅需要消息提示这一组件,那么引入一个大型的组件库是完全多余的,对整个项目来说,也会使其依赖体积过分庞大。
element-plus的消息通知框

此外,还需要考虑到用户自定义的需求。例如,我可能并不希望我的“消息”组件和别人的千篇一律,那么学习如何定制消息组件显然是很有必要的。
那么,如何使用Vue3.x版本的组件式开发风格配合TypeScript来实现这样的功能呢?以下,我将做一个简单的演示,需要注意依赖的版本问题。
我使用的依赖版本

二、分析消息组件的需求

在正式的实现一个消息组件之前,我们先要思考这个组件需要哪些功能,这部分我整理如下:

  1. 在页面顶部中心位置弹出消息通知框,并且能够设置停留在页面上的时间。
  2. 消息通知框有不同的类型,例如警告、错误、、通知、成功。
  3. 当多个消息通知框同时展示时,新出现的消息通知框应该在原有的下方展示,并且当原有的消息通知消失时,能够自动更新位置。

三、消息组件的实现

首先,创建一个Vue3.x的项目。

(一)新建一个Message组件

以下是Message组件代码的一个示例,它支持自定义消息内容,并且能根据props中传入消息类型的不同而展示不同的图标和样式,同时引入了一个名为lucide的UI库,这个库相对轻量级,因此不必担心其占用问题。
唯一需要注意的是,下方的全局样式部分。它定义了两个动画帧,同时定义了一个名为message-fade-out的类,这部分主要是用于给消息组件做入场和出场动画的。
它不能被放入组件私有样式里,因为我们的消息组件后续会作为一个Vue APP挂载到一个HTML Element上,这时由于该元素属于消息组件的父级节点,组件内部样式会对其不起作用。

<template><div class="message" :class="type"><span class="icon" v-if="showIcon"><component :is="iconComponent" /></span><span class="content">{{ content }}</span></div>
</template><script setup lang="ts">
import { computed } from 'vue';
import { Info, CheckCircle, AlertCircle, XCircle } from 'lucide-vue-next'; // 使用 lucide-vue-next 图标库interface Props {content: string;type?: 'info' | 'success' | 'warning' | 'error';showIcon?: boolean;
}const props = withDefaults(defineProps<Props>(), {type: 'info',showIcon: true,
});// 根据类型选择图标
const iconComponent = computed(() => {switch (props.type) {case 'success':return CheckCircle;case 'warning':return AlertCircle;case 'error':return XCircle;default:return Info;}
});
</script><style scoped>
/* 组件的私有样式 */
.message {position: relative;left: 50%;transform: translateX(-50%);padding: 12px 20px;border-radius: 8px;color: white;z-index: 1000;display: flex;align-items: center;gap: 10px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);opacity: 0;animation: fadeIn 0.3s ease forwards;
}.message.info {
background-color: #3498db;
}.message.success {
background-color: #2ecc71;
}.message.warning {
background-color: #f1c40f;
}.message.error {
background-color: #e74c3c;
}.icon {
display: flex;
align-items: center;
}.content {
flex: 1;
word-break: break-word;
}</style><style>
.message-fade-out {animation: fadeOut 0.3s ease forwards !important;
}@keyframes fadeIn {from { opacity: 0; transform: translateX(-50%) translateY(-20px); }to { opacity: 1; transform: translateX(-50%) translateY(0); }
}@keyframes fadeOut {from { opacity: 1; transform: translateX(-50%) translateY(0); }to { opacity: 0; transform: translateX(-50%) translateY(-20px); }
}
</style>

(二)新建一个message.ts的文件

其主要用于实现消息组件的逻辑,同时对外提供消息方法。主要实现思路如下:
1.首先定义一个消息对象和一个消息队列,消息对象由idapp对象和html元素构成。之所以这么做,是因为我们的消息组件需要作为Vue App挂载到一个具体的元素上,他们具备一一对应的关系。这样维护一个消息队列,可以更方便地计算多个消息展示时具体的高度。
2.然后编写展示消息的逻辑:
(1)对于初次使用消息组件的情况,先新建一个外层容器div,这么做可以更好的控制消息组件的样式。
(2)创建一个消息div,添加到上述容器的子节点中,接着消息组件作为APP挂载到该元素上。
(3)更新消息位置,并设置一个定时器,使其到达指定时间后触发隐藏消息的方法。
3.消息隐藏方法的逻辑较为简单,核心为给消息挂载的el元素上添加渐隐的class,使其触发动画效果,并通过侦听器,让其在动画结束后从DOM中移除。
4.更新消息高度的方法,这部分核心是动态地根据队列中消息的index来给其分配合适的高度。
5.最后,将四种类型的消息方法导出。

import { createApp } from 'vue';
import type { App } from 'vue';
import Message from '@/components/Message.vue';type MessageType = 'info' | 'success' | 'warning' | 'error';interface MessageInstance {id: number;app: App<Element>;el: HTMLElement;
}const messageQueue: MessageInstance[] = [];
let messageContainer: HTMLElement | null = null;
let messageId = 0;// 动态计算消息位置
function updateMessagePositions() {let currentTop = 20; // 初始顶部距离messageQueue.forEach((msg) => {const el = msg.el;const height = el.offsetHeight; // 获取实际高度el.style.top = `${currentTop}px`;currentTop += height + 10; // 累加高度和间隙});
}function showMessage(content: string, type: MessageType = 'info', duration: number = 3000) {if (!messageContainer) {messageContainer = document.createElement('div');messageContainer.style.position = 'fixed';messageContainer.style.top = '0';messageContainer.style.left = '0';messageContainer.style.width = '100%';messageContainer.style.pointerEvents = 'none'; // 防止拦截点击事件document.body.appendChild(messageContainer);}const id = messageId++;const el = document.createElement('div');el.style.position = 'absolute';el.style.left = '50%';el.style.transform = 'translateX(-50%)';el.style.transition = 'top 0.8s ease';//添加过渡,这样当一个消息消失时,其他消息的高度变化会有过渡效果。const messageApp = createApp(Message, { content, type });const messageInstance: MessageInstance = { id, app: messageApp, el };messageQueue.push(messageInstance);messageContainer.appendChild(el);messageApp.mount(el);// 等待 DOM 更新后计算位置updateMessagePositions()// 自动隐藏setTimeout(() => hideMessage(id), duration);
}function hideMessage(id: number) {const index = messageQueue.findIndex((msg) => msg.id === id);if (index === -1) return;const [messageInstance] = messageQueue.splice(index, 1);const el = messageInstance.el;// 添加淡出动画类el.classList.add('message-fade-out');// 动画结束后移除元素const onAnimationEnd = () => {el.removeEventListener('animationend', onAnimationEnd);messageInstance.app.unmount();el.remove();updateMessagePositions();};el.addEventListener('animationend', onAnimationEnd, { once: true });}export default {info(content: string, duration?: number) {showMessage(content, 'info', duration);},success(content: string, duration?: number) {showMessage(content, 'success', duration);},warning(content: string, duration?: number) {showMessage(content, 'warning', duration);},error(content: string, duration?: number) {showMessage(content, 'error', duration);},
};

(三)测试消息组件

我们可以任意新建一个新的组件,并通过按钮触发消息通知,例如:

const handleClick = () => {message.info('这是一个比较长的句子字字字字字……', 5000)
}

页面上展示效果如下:

四、总结

恭喜你!顺利看到这里,想必已经掌握了如何自主实现一个消息组件。在这个过程中,相信你对DOM操作的理解也进一步加深了,接下来可以任意定制想要的内容啦!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com