elementui在任意页面点击消息,弹出消息对应页面处理弹窗

需求:在系统的任意页面点击消息都能弹出对应页面中的操作弹窗

思路:

1、创建一个全局组件,这个组件要能在任何地方都被打开(所以放在了app.vue页面)

2、使用component 组件找到要打开的页面路径

3、在被打开的页面中创建方法并暴露出去,使第二步找到组件后能调用方法打开相应的弹窗

3.1、打开页面后要将页面中所有html都隐藏只保留弹窗

不足:这样会导致一个问题就是再打开的时候其实是两个页面,性能相对不好,并且也会加载被打开页面中的所有方法,这样浪费性能但是代码上统一性,而且也不会出现部分组件弹窗依赖接口太多需要一个一个写进去的问题

封装全局显示组件:

javascript 复制代码
<template>
  <component v-if="dynamicComponent"
    ref="dynamicComponentRef"
    :parentObj="parentObj"
    :is="dynamicComponent.default"></component>
</template>
<script setup lang="ts">
const dynamicComponentRef: any = ref<HTMLElement | null>(null);
const dynamicComponent = ref<null | any>(null);
const parentObj = ref<msgUrlParams>();
// 预加载所有文件并映射地址
const modules = import.meta.glob('./views/**/*.vue');
const loadComponent = async (configObj: msgUrlParams) => {
  parentObj.value = configObj;
  try {
    dynamicComponent.value = await load(configObj.url);
    await nextTick();
    // 调用找到的组件的eventStack方法
    dynamicComponentRef.value?.eventStack(configObj);
  } catch (error) {
    console.error('加载组件失败:', error);
    dynamicComponent.value = null;
  }
};
const load = async (componentPath: string) => {
  try {
    // 使用 import.meta.glob 加载组件
    const path = componentPath.replace(/\.vue$/, '');
    const componentLoader = modules[`./views/${path}.vue`];
    if (!componentLoader) throw new Error(`Component not found: ${path}`);
    const module = await componentLoader();
    return module;
  } catch (error) {
    console.error('加载组件失败:', error);
    return null;
  }
};
defineExpose({
  loadComponent
});
</script>

在app.vue页面引入这个组件:

javascript 复制代码
<HandleDialog ref="dialogRef"
  style="position: absolute;bottom:0 ;padding: 0;" />

// 消息弹窗
const dialogRef: any = ref<HTMLElement | null>(null);
const loadComponent = async (configObj: msgUrlParams) => {
  dialogRef.value.loadComponent(configObj);
};


// 将app.vue的方法注入到全局使得全局组件都能调用
provide('loadComponent', loadComponent);

调用:(如消息中心页面,首页的消息推送地方)

javascript 复制代码
// 消息弹窗Url参数
interface msgUrlParams {
   eventId: string,//消息事件id
   url: string,//跳转url
   eventType: number,// '0:view'|'1:audit' | 'edit' | 'add' , // 事件类型
   eventParams: any,// 其他信息
 }
// 引入app的依赖
const loadComponent = inject('loadComponent') as any;
// 点击事件
const click(item:msgUrlParams)=>{
  const obj = {
    eventId: item.dataId, // 页面中弹窗数据的id
    url: item.msgLink, // 页面的路径
    eventType: item.msgState, // 处理状态
  };
  loadComponent(obj);
}

被调用的组件增加方法:

javascript 复制代码
const isShowList = ref<boolean>(true);// 是否显示背景(把页面中的背景全部隐藏掉,这样加载这个组件的时候就会只显示弹窗了)
const eventStack = async (parentObj: msgUrlParams) => {
  isShowList.value = false;
   // 根据传入的操作事件 id 获取到操作事件的详情
  const res = await getMaint(parentObj.eventId);
   // 根据状态判断是调用哪个弹窗的方法
  if (parentObj.eventType == 1) {
    handleFlowCheck(res.data);
  } else if (parentObj.eventType == 0) {
    printView(res.data);
  } else if (parentObj.eventType == 2) {
    handleAdd();
  }
};

记得要把页面给隐藏了,弹窗还是能正常弹出

相关推荐
疯狂的沙粒1 分钟前
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
前端·uni-app·html
小妖6665 分钟前
html 滚动条滚动过快会留下边框线
前端·html
heroboyluck19 分钟前
Svelte 核心语法详解:Vue/React 开发者如何快速上手?
前端·svelte
海的诗篇_20 分钟前
前端开发面试题总结-JavaScript篇(二)
开发语言·前端·javascript·typescript
琹箐31 分钟前
ant-design4.xx实现数字输入框; 某些输入法数字需要连续输入两次才显示
前端·javascript·anti-design-vue
程序员-小李31 分钟前
VuePress完美整合Toast消息提示
前端·javascript·vue.js
Uyker1 小时前
从零开始制作小程序简单概述
前端·微信小程序·小程序
Dontla5 小时前
为什么React列表项需要key?(React key)(稳定的唯一标识key有助于React虚拟DOM优化重绘大型列表)
javascript·react.js·ecmascript
EndingCoder5 小时前
React从基础入门到高级实战:React 实战项目 - 项目三:实时聊天应用
前端·react.js·架构·前端框架
阿阳微客7 小时前
Steam 搬砖项目深度拆解:从抵触到真香的转型之路
前端·笔记·学习·游戏