MUI - 如何打开对话框 imperatively/programmatically
MUI - How to open Dialog imperatively/programmatically
通常这就是您使用 MUI 的方式 Dialog
。下面的代码取自文档:
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open Dialog
</Button>
<Dialog open={open} onClose={handleClose}>
{...}
</Dialog>
</div>
);
}
但我希望它以命令方式创建 Dialog
,有点像发射后忘记。我不想在需要创建其他组件时 嵌入 Dialog
组件。理想情况下我想这样称呼它
createDialog(<>
<h1>My Dialog</h1>
<span>My dialog content</span>
<button onClick={() => closeDialog()}>Close</button>
</>)
所以我的组件定义看起来像这样
const createDialog = () => {
// ???
}
const closeDialog = () => {
// ???
}
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => setOpen(true);
const handleClose = () => {
createDialog(<>
<h1>My Dialog</h1>
<span>My dialog content</span>
<button onClick={() => closeDialog()}>Close</button>
</>)
};
return (
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open Dialog
</Button>
);
}
您可以使用 React 的 Provider
模式重用对话框。 React官方文档已经解释的很详细了,这里就不再赘述了。
首先创建一个自定义 Provider
组件,在这种情况下我将调用 DialogProvider
。此组件将管理本地状态中 Dialog
的列表。
const DialogContext = React.createContext();
export default function DialogProvider({ children }) {
const [dialogs, setDialogs] = React.useState([]);
return (
<DialogContext.Provider {...}>
{children}
</DialogContext.Provider>
);
}
如您所见,我们这里有一个对话框数组,它包含在渲染时将映射到实际 <Dialog />
组件的对话框属性。
export default function DialogProvider({ children }) {
const [dialogs, setDialogs] = React.useState([]);
return (
<DialogContext.Provider {...}>
{children}
{dialogs.map((dialog, i) => {
return <DialogContainer key={i} {...dialog} />;
})}
</DialogContext.Provider>
);
}
<DialogContainer/>
是 <Dialog/>
的父组件。 把任何你想重复使用的东西放在那里。这是让您入门的最简单示例。
function DialogContainer(props: DialogContainerProps) {
const { children, open, onClose, onKill } = props;
return (
<Dialog open={open} onClose={onClose} onExited={onKill}>
{children}
</Dialog>
);
}
我们可以像往常一样使用 setState
创建和删除对话框。
const [dialogs, setDialogs] = React.useState([]);
const createDialog = (option) => {
const dialog = { ...option, open: true };
setDialogs((dialogs) => [...dialogs, dialog]);
};
const closeDialog = () => {
setDialogs((dialogs) => {
const latestDialog = dialogs.pop();
if (!latestDialog) return dialogs;
if (latestDialog.onClose) latestDialog.onClose();
return [...dialogs].concat({ ...latestDialog, open: false });
});
};
但是我们这里定义的时候在其他组件中怎么调用呢?好吧,请记住我们在这里使用 Provider
组件,这意味着我们可以向下传递上下文数据以便其他组件可以引用,在这种情况下我们要向下传递 createDialog
和 closeDialog
.
const [dialogs, setDialogs] = React.useState([]);
const createDialog = (option) => {/*...*/};
const closeDialog = () => {/*...*/};
const contextValue = React.useRef([createDialog, closeDialog]);
return (
<DialogContext.Provider value={contextValue.current}>
{children}
{dialogs.map((dialog, i) => ...)}
</DialogContext.Provider>
);
我们差不多完成了,现在我们需要将 DialogProvider
添加到组件树中。
export default function App() {
return (
<DialogProvider>
<App {...} />
</DialogProvider>
);
}
但在我们使用它们之前,我们应该创建一个钩子来轻松地从父级访问上下文。所以在你的 DialogProvider.jsx
export const useDialog = () => React.useContext(DialogContext);
现在我们可以这样使用了。
import { useDialog } from "./DialogProvider";
export default function Content() {
const [openDialog, closeDialog] = useDialog();
const onOpenDialog = () => {
openDialog({
children: (
<>
<DialogTitle>This dialog is opened imperatively</DialogTitle>
<DialogContent>Some content</DialogContent>
<DialogActions>
<Button color="primary" onClick={closeDialog}>Close</Button>
</DialogActions>
</>
)
});
};
return (
<Button variant="contained" onClick={onOpenDialog}>
Show dialog
</Button>
);
}
现场演示
您可以在此处体验现场演示
通常这就是您使用 MUI 的方式 Dialog
。下面的代码取自文档:
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
return (
<div>
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open Dialog
</Button>
<Dialog open={open} onClose={handleClose}>
{...}
</Dialog>
</div>
);
}
但我希望它以命令方式创建 Dialog
,有点像发射后忘记。我不想在需要创建其他组件时 嵌入 Dialog
组件。理想情况下我想这样称呼它
createDialog(<>
<h1>My Dialog</h1>
<span>My dialog content</span>
<button onClick={() => closeDialog()}>Close</button>
</>)
所以我的组件定义看起来像这样
const createDialog = () => {
// ???
}
const closeDialog = () => {
// ???
}
export default function AlertDialog() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => setOpen(true);
const handleClose = () => {
createDialog(<>
<h1>My Dialog</h1>
<span>My dialog content</span>
<button onClick={() => closeDialog()}>Close</button>
</>)
};
return (
<Button variant="outlined" color="primary" onClick={handleClickOpen}>
Open Dialog
</Button>
);
}
您可以使用 React 的 Provider
模式重用对话框。 React官方文档已经解释的很详细了,这里就不再赘述了。
首先创建一个自定义 Provider
组件,在这种情况下我将调用 DialogProvider
。此组件将管理本地状态中 Dialog
的列表。
const DialogContext = React.createContext();
export default function DialogProvider({ children }) {
const [dialogs, setDialogs] = React.useState([]);
return (
<DialogContext.Provider {...}>
{children}
</DialogContext.Provider>
);
}
如您所见,我们这里有一个对话框数组,它包含在渲染时将映射到实际 <Dialog />
组件的对话框属性。
export default function DialogProvider({ children }) {
const [dialogs, setDialogs] = React.useState([]);
return (
<DialogContext.Provider {...}>
{children}
{dialogs.map((dialog, i) => {
return <DialogContainer key={i} {...dialog} />;
})}
</DialogContext.Provider>
);
}
<DialogContainer/>
是 <Dialog/>
的父组件。 把任何你想重复使用的东西放在那里。这是让您入门的最简单示例。
function DialogContainer(props: DialogContainerProps) {
const { children, open, onClose, onKill } = props;
return (
<Dialog open={open} onClose={onClose} onExited={onKill}>
{children}
</Dialog>
);
}
我们可以像往常一样使用 setState
创建和删除对话框。
const [dialogs, setDialogs] = React.useState([]);
const createDialog = (option) => {
const dialog = { ...option, open: true };
setDialogs((dialogs) => [...dialogs, dialog]);
};
const closeDialog = () => {
setDialogs((dialogs) => {
const latestDialog = dialogs.pop();
if (!latestDialog) return dialogs;
if (latestDialog.onClose) latestDialog.onClose();
return [...dialogs].concat({ ...latestDialog, open: false });
});
};
但是我们这里定义的时候在其他组件中怎么调用呢?好吧,请记住我们在这里使用 Provider
组件,这意味着我们可以向下传递上下文数据以便其他组件可以引用,在这种情况下我们要向下传递 createDialog
和 closeDialog
.
const [dialogs, setDialogs] = React.useState([]);
const createDialog = (option) => {/*...*/};
const closeDialog = () => {/*...*/};
const contextValue = React.useRef([createDialog, closeDialog]);
return (
<DialogContext.Provider value={contextValue.current}>
{children}
{dialogs.map((dialog, i) => ...)}
</DialogContext.Provider>
);
我们差不多完成了,现在我们需要将 DialogProvider
添加到组件树中。
export default function App() {
return (
<DialogProvider>
<App {...} />
</DialogProvider>
);
}
但在我们使用它们之前,我们应该创建一个钩子来轻松地从父级访问上下文。所以在你的 DialogProvider.jsx
export const useDialog = () => React.useContext(DialogContext);
现在我们可以这样使用了。
import { useDialog } from "./DialogProvider";
export default function Content() {
const [openDialog, closeDialog] = useDialog();
const onOpenDialog = () => {
openDialog({
children: (
<>
<DialogTitle>This dialog is opened imperatively</DialogTitle>
<DialogContent>Some content</DialogContent>
<DialogActions>
<Button color="primary" onClick={closeDialog}>Close</Button>
</DialogActions>
</>
)
});
};
return (
<Button variant="contained" onClick={onOpenDialog}>
Show dialog
</Button>
);
}
现场演示
您可以在此处体验现场演示