1.二次封装防止多次重复弹窗
@/utils/resetMessage.ts
ts
// import { ElMessage } from "element-plus"; //按需引入时,这里不需要引入,否则样式失效
let messageInstance: any | null = null; //定义一个变量
// 这种方式失败了,不知道为什么
// const resetMessage = (options: {}) => {
// if (messageInstance && messageInstance.closeAll) {
// messageInstance.closeAll();
// }
// //@ts-ignore
// // return (messageInstance = ElMessage(options));
// messageInstance = ElMessage(options);
// };
//封装ElMessage的函数:
const resetMessage = (options) => {
//如果实例已经被创建了,并且实例没有被关闭
if (messageInstance && messageInstance.close) {
messageInstance.close(); //那么就直接关闭
}
//@ts-ignore //必须加这个注释,方式ts检查报错
messageInstance = ElMessage(options); //调用原本的El组件
};
//识别resetMessage函数的参数类型,以适应.success等函数
["error", "success", "info", "warning"].forEach((type) => {
resetMessage[type] = (options: any) => {
if (typeof options === "string") {
options = {
message: options, //将传入的参数赋值给message属性
};
}
options.type = type; //将后面.success赋值给type属性
return resetMessage(options); //调用上面的函数
};
});
export const Message = resetMessage; //这里导出的是const resetMessage这个函数
2.全局绑定ElMessage并用scss自定义样式
@/plugins/elementPlus/index.ts
ts
// src/plugins/elementPlus/index.ts
import type { App } from "vue";
// 需要全局引入一些组件,如ElScrollbar,不然一些下拉项样式有问题
// 因为配置了按需引入,所以这里一定不要再引入了,否则样式会有问题!
// import { ElLoading, ElScrollbar, ElMessage } from "element-plus";
//改为引入二次封装的ElMessage,禁止弹窗多次出现
import { Message } from "@/utils/resetMessage";
//@ts-ignore
const plugins = [ElLoading];
//@ts-ignore
const components = [ElScrollbar];
//定义函数对app进行封装,绑定一些二次封装的El组件
export const setupElementPlus = (app: App<Element>) => {
plugins.forEach((plugin) => {
app.use(plugin);
});
components.forEach((component) => {
app.component(component.name, component);
});
const ElMessageCfg = { duration: 2000, customClass: "globalElMessageStyle" }; //前面为多长时间消失,后面为样式class
//将二次封装的El组件绑定到全局
app.config.globalProperties.$ElMessage = (msg) => {
//@ts-ignore
return Message({ message: msg, ...ElMessageCfg }); //传入消息msg和样式等信息参数
};
app.config.globalProperties.$ElMessage.success = (msg) => {
//@ts-ignore
return Message.success({ message: msg, ...ElMessageCfg });
};
app.config.globalProperties.$ElMessage.warning = (msg) => {
//@ts-ignore
return Message.warning({ message: msg, ...ElMessageCfg });
};
app.config.globalProperties.$ElMessage.info = (msg) => {
//@ts-ignore
return Message.info({ message: msg, ...ElMessageCfg });
};
app.config.globalProperties.$ElMessage.error = (msg) => {
//@ts-ignore
return Message.error({ message: msg, ...ElMessageCfg });
};
};
@/styles/component.scss
scss
.globalElMessageStyle {
z-index: 3000 !important;
border: 1px saddlebrown solid !important; //必须加!important
// position: absolute;
// left: 500px;
}
@/styles/index.scss
scss
@import "./component.scss";
3.定义全局获取vm实例的方法
@/utils/useCurrentInstance.ts
ts
//注意:appContext.config.globalProperties与proxy基本上是等价的,这里我们选用globalProperties
import { ComponentInternalInstance, getCurrentInstance } from "vue";
export default function useCurrentInstance() {
const { appContext } = getCurrentInstance() as ComponentInternalInstance;
const globalProperties = appContext?.config.globalProperties; //这里最好加一个?,因为返回类型可能存在null,所以要在此处添加断言,在proxy后面添加?来过滤null的结果,否则到了线上可能会报错
return {
globalProperties,
};
}
4.对全局的ElMessage进行使用
1.main.ts
ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "@/router";
import pinia from "@/store";
// 引入element-plus的封装方法
import { setupElementPlus } from "@plugins/elementPlus/index";
// 引入全局样式(定义了ElMessage的样式
import "@/styles/index.scss";
// 原来的创建实例的方法:
// const app = createApp(App);
// app.use(router);
// app.use(pinia);
// app.provide("$message", ElMessage);
// app.mount("#app");
//现在的创建实例的方法:
const setupAll = async () => {
const app = createApp(App);
setupElementPlus(app); //相当于进入给app加工一下,没什么太大的区别
app.use(router);
app.use(pinia);
app.mount("#app");
};
setupAll(); //调用创建实例
2.HelloWorld.vue
vue
<script setup lang="ts">
import { h } from "vue";
// import { ElMessage } from "element-plus";
// import { getCurrentInstance } from "vue";
// import { Message } from "@/utils/resetMessage";
import useCurrentInstance from "@/utils/useCurrentInstance";
// 未定义全局方法时:
// const { proxy } = getCurrentInstance() as any; //这里也必须要as any,否则下面在.属性的时候会报错!
// const { ctx } = getCurrentInstance() as any; //这里必须要as any
//定义了全局方法之后:
const { globalProperties } = useCurrentInstance();
//建议用箭头函数写法来定义函数
const showMessage = () => {
//测试普通的ElMessage:
// ElMessage.success("你好");
// ElMessage.error("你好");
//测试二次封装El的resetMessage:
// Message.success("你好");
// Message.error("你好");
// Message({
// message: "登录注册成功",
// type: "success",
// });
//测试传入自定义Vnode时,普通的和封装的区别:
//原来的写法:
//@ts-ignore
// ElMessage({
// message: h('p', null, [
// h('span', null, 'Message can be '),
// h('i', { style: 'color: teal' }, 'VNode'),
// ]),
// })
//现在的写法:不用写k-v,直接写v即可!
// proxy.$ElMessage(
// h("p", null, [
// h("span", null, "Message can be "),
// h("i", { style: "color: teal" }, "VNode"),
// ])
// );
// 测试非全局获取vm实例:
// proxy.$ElMessage.success("成功");
// proxy.$ElMessage.error("失败"); //只会显示最后一个
// 测试全局获取vm实例:
globalProperties.$ElMessage.success("成功");
globalProperties.$ElMessage.error("失败");
};
</script>