这些天,我在玩Ionic React,因此尝试了不同的组件。我几乎在所有应用程序中都没有例外地使用过模式之一。尽管它的专用文档非常简洁,但我想进一步说明一下,因为我喜欢在它们自己的单独组件中声明它们。这就是为什么我要写这篇新的博客文章。
入门
要向应用程序中添加模式,请按照文档中显示的步骤进行操作(告诉您,此文档有据可查)。我们使用组件,IonModal
并且为了触发它的打开和关闭,我们还使用状态(借助于useState
钩子)来修改其property isOpen
。
import React, {useState} from 'react';
import {IonModal, IonButton, IonContent} from '@ionic/react';
export const Tab1: React.FC = () => {
const [showModal, setShowModal] = useState(false);
return (
<IonContent>
<IonModal isOpen={showModal}>
<p>This is the modal content.</p>
<IonButton onClick={() => setShowModal(false)}>
Close Modal
</IonButton>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>
Show Modal
</IonButton>
</IonContent>
);
};
export default Tab1;
请注意,我已经使用*tab
入门工具包来开发本文,这就是上面页面名称为Tab1
。* 的原因。
创建一个组件
模式很快就会变得和页面一样复杂,这就是为什么我习惯在自己的组件中声明它们。然后,让我们尝试在一个单独的新文件(例如)中创建一个新文件MyModal.tsx
。
import React from 'react';
import {IonHeader, IonContent, IonToolbar, IonTitle} from '@ionic/react';
class MyModal extends React.Component {
render() {
return <>
<IonHeader>
<IonToolbar color="primary">
<IonTitle>My Modal</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p>This is the modal content.</p>
</IonContent>
</>
};
}
export default MyModal;
创建它之后,我们可以在页面中使用它来替换模式的先前内容。
import React, { useState } from 'react';
import { IonModal, IonButton, IonContent} from '@ionic/react';
import MyModal from './MyModal';
export const Tab1: React.FC = () => {
const [showModal, setShowModal] = useState(false);
return (
<IonContent>
<IonModal isOpen={showModal}>
<MyModal></MyModal>
<IonButton onClick={() => setShowModal(false)}>
Close Modal
</IonButton>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>
Show Modal
</IonButton>
</IonContent>
);
};
export default Tab1;
关闭模态
超级,我们迈出了第一步,现在我们在单独的组件中声明了一个模式。但是,在上面的示例中,关闭模态的操作(IonButton
将显示状态设置为的按钮false
)仍然呈现在组件外部,这在设计上有点不幸,因为我认为在模式本身的标题中呈现这样的动作。
为了将此按钮移到模式中,我实际上找到了两种可能的解决方案。一种使用callback
,可能是最干净的一种,另一种使用references
。
可能还有更多,而我很高兴听到他们的消息。因此,请给我您的评论,并在此先感谢您的分享。
打回来
在此解决方案中,我们希望将回调传递给组件以关闭模式。我们通过一个新属性对其进行了增强,该属性也用于标题中以添加相关按钮。
import React from 'react';
import {IonHeader, IonContent, IonToolbar, IonTitle, IonButtons, IonButton, IonIcon} from '@ionic/react';
type MyModalProps = {
closeAction: Function;
}
class MyModal extends React.Component<MyModalProps> {
render() {
return <>
<IonHeader>
<IonToolbar color="primary">
<IonTitle>My Modal</IonTitle>
<IonButtons slot="end">
<IonButton onClick={() => this.props.closeAction()}>
<IonIcon name="close" slot="icon-only"></IonIcon>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p>This is the modal content.</p>
</IonContent>
</>
};
}
export default ({closeAction}: { closeAction: Function }) => (
<MyModal closeAction={closeAction}>
</MyModal>
)
修改组件后,我们可以在页面中创建一个新函数来将显示状态设置为false
,并将其作为回调传递给组件。
import React, {useState} from 'react';
import {IonModal, IonButton, IonContent} from '@ionic/react';
import MyModal from './MyModal';
export const Tab1: React.FC = () => {
const [showModal, setShowModal] = useState(false);
async function closeModal() {
await setShowModal(false);
}
return (
<IonContent>
<IonModal isOpen={showModal}>
<MyModal closeAction={closeModal}></MyModal>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>
Show Modal
</IonButton>
</IonContent>
);
};
export default Tab1;
参考文献
另一种可能的解决方案是使用DOM引用来消除模态。
import React, {RefObject} from 'react';
import {IonHeader, IonContent, IonToolbar, IonTitle, IonButtons, IonButton, IonIcon} from '@ionic/react';
class MyModal extends React.Component {
headerRef: RefObject<HTMLIonHeaderElement> = React.createRef();
async closeModal() {
if (!this.headerRef || !this.headerRef.current) {
return;
}
await (this.headerRef.current.closest('ion-modal') as
HTMLIonModalElement).dismiss();
}
render() {
return <>
<IonHeader ref={this.headerRef}>
<IonToolbar color="primary">
<IonTitle>My Modal</IonTitle>
<IonButtons slot="end">
<IonButton onClick={() => this.closeModal()}>
<IonIcon name="close" slot="icon-only"></IonIcon>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p>This is the modal content 3.</p>
</IonContent>
</>
};
}
export default MyModal;
上面的方法的效果是 state
,在我们的页面中用于显示目的的our可能最终不再与模式的有效状态同步,因为我们使用DOM关闭了它。为了克服这种情况,我们可以在关闭对话框后同步信息。
import React, {useState} from 'react';
import {IonModal, IonButton, IonContent} from '@ionic/react';
import MyModal from './MyModal';
export const Tab1: React.FC = () => {
const [showModal, setShowModal] = useState(false);
return (
<IonContent>
<IonModal isOpen={showModal}
onDidDismiss={() => setShowModal(false)}>
<MyModal></MyModal>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>
Show Modal
</IonButton>
</IonContent>
);
};
export default Tab1;
但是不幸的是,这种方法有一个缺点。当我们修改状态以使其同步时,我们的组件将被“渲染”。因此,它的性能比解决方案要差一些callback
,这就是为什么我找到了第一台解决方案更清洁的原因。
旁注:昨天晚上,我花了几个小时尝试不成功地shouldComponentUpdate
分别包装React.Memo
模态组件,以免在取消模态后修改状态后不再呈现页面。也许有可能,我也很高兴再次听到与此有关的任何提示😉
传递参数
在前面的示例中,我们已经使用了一个属性来传递回调以关闭模式。同样,我们可以使用相同的方法来定义任何其他属性。
import React from 'react';
import {IonHeader, IonContent, IonToolbar, IonTitle, IonButtons, IonButton, IonIcon} from '@ionic/react';
type MyModalProps = {
closeAction: Function;
text: string;
}
class MyModal extends React.Component<MyModalProps> {
render() {
return <>
<IonHeader>
<IonToolbar color="primary">
<IonTitle>My Modal</IonTitle>
<IonButtons slot="end">
<IonButton onClick={() => this.props.closeAction()}>
<IonIcon name="close" slot="icon-only"></IonIcon>
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding">
<p>{this.props.text}</p>
</IonContent>
</>
};
}
export default ({closeAction, text}: { closeAction: Function, text: string }) => (
<MyModal closeAction={closeAction} text={text}>
</MyModal>
)
因此,将页面中的任何其他参数传递给我们的模态组件。
import React, {useState} from 'react';
import {IonModal, IonButton, IonContent} from '@ionic/react';
import MyModal from './MyModal';
export const Tab1: React.FC = () => {
const [showModal, setShowModal] = useState(false);
async function closeModal() {
await setShowModal(false);
}
return (
<IonContent>
<IonModal isOpen={showModal}>
<MyModal closeAction={closeModal}
text="This is the updated modal content.">
</MyModal>
</IonModal>
<IonButton onClick={() => setShowModal(true)}>
Show Modal
</IonButton>
</IonContent>
);
};
export default Tab1;
超越无限🚀