对于弹出层组件,React Portals 无疑是提供了一种很好的解决方案(Protal相关也能够看这里)。 若是没有 Portal
的话弹出层要怎么处理呢,好比React Native
环境中?html
React Native
中可使用Modal
组件,可是由于层级问题以及与其余组件的兼容性也是常常被诟病。react
咱们来解决这个问题。函数
Modal
的本质就是一个在组件树上拥有更高显示层级的view
,能够覆盖整个页面,有背景色和透明度,蒙层背景中包含弹出的显示内容区,好比一个提示,对话框等等。布局
将蒙层的Modal
和内容区分开,作成父子组件的组合模式,自定义并暴露显示子组件的方法,将子组件整个传入Modal
中显示,便可达到弹出内容的效果,再提供关闭Modal
的方法,用于命令式地设置Modal
的隐藏。测试
也就是说咱们的组件知足这些条件:flex
Modal
的方法命令式的调用无疑须要用到Ref
了,开始实现:设计
定义组件。包含两个state
,一个view
,一个控制显示与隐藏的flag
。暴露出两个方法,显示和关闭。须要显示的内容view
经过方法参数传入。code
import React, { useImperativeHandle, useState } from "react"; function Modal(props, ref) { const [view, setView] = useState([]); const [isShow, setIsShow] = useState(0); useImperativeHandle(ref, () => ({ init: (view) => { setView(view); setIsShow(true); }, close: () => setIsShow(false), })); if (isShow) { return <div style={sts.wrap}>{view}</div>; } else { return null; } } export default React.forwardRef(Modal); export const modalRef = React.createRef(); export const TopModal = { show, close }; function show(view) { modalRef.current.init(view); } function close() { modalRef.current.close(); } // 蒙层 style const sts = { wrap: { zIndex: 100, top: 0, left: 0, width: "100%", height: "100%", position: "absolute", backgroundColor: "rgba(0,0,0,0.6)", display: "flex", justifyContent: "center", alignItems: "center", }, };
将组件放到组件树较高层级的位置,这里直接放到了和App
同级的位置,将定义的Ref
传入。component
import Modal, { modalRef } from "./refmodal/component"; ReactDOM.render( <React.StrictMode> <App /> <Modal ref={modalRef} /> </React.StrictMode>, document.getElementById("root") );
测试运行效果。htm
export default function ModalRefTest() { function openModal() { const view = ( <div style={{ width: 100, height: 100, backgroundColor: "#FFF" }}> <button onClick={close}>关闭</button> </div> ); TopModal.show(view); } function close() { TopModal.close(); } return ( <div> <button onClick={openModal}>打开</button> </div> ); }
弹出框的内容很简单,只有一个按钮,用于关闭当前Modal
,show
方法将内容区整个div
传入。
效果:
到这里,一个简易版本的Modal
已经有了初步效果。
将要显示的内容作成一个组件,直接将组件view
传入Modal
中显示。这样的方式,能够作成对话框,Toast,各类提示。这其中可能还须要对背景色做出修改,这些也能够经过函数参数的方式传入到组件中来处理。
也能够将布局的关键属性传入,组件决定内容区显示在中间仍是顶部,仍是底部。由此再能够扩展出actionSheet
组件。
能够将API
设计成show(view,config)
的形式,读取config
的内容,动态设置样式和布局显示。
经过React
的方式添加的高层级view
显示,这一思路彻底适用于React Native
。