想通过api命令的方式打开消息弹窗。
以前一直在写vue,用element-plus组件库,最新在写 react 脑子就有点锈到了。写的习惯上不同。
想实现通过 ref 的方式打开消息模态窗,可以是结果:
想通过forwardRef useImperativeHandle 将组件modal 的open 方法暴露出去,在父组件通过ref的方式调用。 行不通。
组件实现:
import { MessageInterface } from "@/utils/message";
import { Modal, ModalClose, ModalDialog, Sheet, Typography } from "@mui/joy";
import { useState } from "react";
const Message = (props: any) => {
const [open, setOpen] = useState<boolean>(true);
const { title, message, duration, color }: MessageInterface = { ...props }
return <>
<div>
<Modal open={open}
onClose={() => setOpen(false)}>
<ModalDialog color={color} variant="plain">
<ModalClose variant="plain" sx={{ m: 1 }} />
<Typography
component="h2"
level="h4"
textColor="inherit"
fontWeight="lg"
color={color}
>
{title}
</Typography>
<Typography >
{message}
</Typography>
</ModalDialog>
</Modal>
</div>
</>
};
export default Message;
组件实例创建就open 就为true 就是打开状态。
消息api react 18写法
import Message from "@/components/message"
import { createRoot } from 'react-dom/client';
export interface MessageInterface {
title: string,
message: string,
duration: number,
color?: any
}
const message: any = {
dom: null,
success({ title, message }: MessageInterface) {
// 创建一个dom
this.dom = document.createElement('div');
// 定义组件,
const JSXdom = (<Message title={title} message={message} color="success" > </Message>);
// 渲染DOM
const root = createRoot(this.dom)
document.body.appendChild(this.dom);
root.render(JSXdom)
// 置入到body节点下
},
error({ title, message }: MessageInterface) {
// 创建一个dom
this.dom = document.createElement('div');
// 定义组件,
const JSXdom = (<Message title={title} message={message} color="danger" > </Message>);
const root = createRoot(this.dom)
document.body.appendChild(this.dom);
root.render(JSXdom)
},
};
export default message;
消息api react 18-写法
import Message from "@/components/message"
import ReactDOM from "react-dom"
export interface MessageInterface {
title: string,
message: string,
duration: number,
color?: any
}
const message: any = {
dom: null,
success({ title, message }: MessageInterface) {
// 创建一个dom
this.dom = document.createElement('div');
// 定义组件,
const JSXdom = (<Message title={title} message={message} color="success" > </Message>);
// 渲染DOM
ReactDOM.render(JSXdom,this.dom)
document.body.appendChild(this.dom);
// 置入到body节点下
},
error({ title, message }: MessageInterface) {
// 创建一个dom
this.dom = document.createElement('div');
// 定义组件,
const JSXdom = (<Message title={title} message={message} color="danger" > </Message>);
ReactDOM.render(JSXdom,this.dom)
document.body.appendChild(this.dom);
},
};
export default message;
react18 推荐使用 createRoot ,以前的版本可以使用 ReactDOM.render的方式。
待优化:每次弹出消息都创建一个dom,有点太浪费了。后面看关闭后删除。
还有一种实现方式,就是在根节点就创建消息弹窗组件,通过消息订阅的方式打开弹窗,但是我是在next上的多根节点布局,所以,暂时不考虑了。
根节点注册消息组件,组件初始化的时候,订阅消息,后面其他业务上,可直接通过消息订阅机制出发消息弹窗。