zoukankan      html  css  js  c++  java
  • 制作一个命令式的 React 弹出层组件 (适用 React Native)

    对于弹出层组件,React Portals 无疑是提供了一种很好的解决方案(Protal相关也可以看这里)。 如果没有 Portal的话弹出层要怎么处理呢,比如React Native环境中?

    React Native中可以使用Modal组件,但是因为层级问题以及与其他组件的兼容性也是经常被诟病。

    我们来解决这个问题。

    曲径通幽


    Modal的本质就是一个在组件树上拥有更高显示层级的view,可以覆盖整个页面,有背景色和透明度,蒙层背景中包含弹出的显示内容区,比如一个提示,对话框等等。

    将蒙层的Modal和内容区分开,做成父子组件的组合模式,自定义并暴露显示子组件的方法,将子组件整个传入Modal中显示,即可达到弹出内容的效果,再提供关闭Modal的方法,用于命令式地设置Modal的隐藏。

    也就是说我们的组件满足这些条件:

    • 更高的显示层级
    • 通过方法填入子组件,并暴露显示和隐藏Modal的方法

    实现和效果


    命令式的调用无疑需要用到Ref了,开始实现:

    1. 定义组件。包含两个state,一个view,一个控制显示与隐藏的flag。暴露出两个方法,显示和关闭。需要显示的内容view通过方法参数传入

      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,
           "100%",
          height: "100%",
          position: "absolute",
          backgroundColor: "rgba(0,0,0,0.6)",
          display: "flex",
          justifyContent: "center",
          alignItems: "center",
        },
      };
      
      
    2. 将组件放到组件树较高层级的位置,这里直接放到了和App同级的位置,将定义的Ref传入。

      import Modal, { modalRef } from "./refmodal/component";
      
      ReactDOM.render(
        <React.StrictMode>
          <App />
          <Modal ref={modalRef} />
        </React.StrictMode>,
        document.getElementById("root")
      );
      
    3. 测试运行效果。

      export default function ModalRefTest() {
        function openModal() {
          const view = (
            <div style={{  100, height: 100, backgroundColor: "#FFF" }}>
              <button onClick={close}>关闭</button>
            </div>
          );
          TopModal.show(view);
        }
        function close() {
          TopModal.close();
        }
        return (
          <div>
            <button onClick={openModal}>打开</button>
          </div>
        );
      }
      

      弹出框的内容很简单,只有一个按钮,用于关闭当前Modalshow方法将内容区整个div传入。

      效果:

    到这里,一个简易版本的Modal已经有了初步效果。

    扩展方向


    将要显示的内容做成一个组件,直接将组件view传入Modal中显示。这样的方式,可以做成对话框,Toast,各种提示。这其中可能还需要对背景色作出修改,这些也可以通过函数参数的方式传入到组件中来处理。

    也可以将布局的关键属性传入,组件决定内容区显示在中间还是顶部,还是底部。由此再可以扩展出actionSheet组件。

    可以将API设计成show(view,config)的形式,读取config的内容,动态设置样式和布局显示。

    通过React的方式添加的高层级view显示,这一思路完全适用于React Native

  • 相关阅读:
    (转)MVC3+EF4.1学习系列(十一)EF4.1常见的问题解决
    (转)iReaper for wp7正式发布
    (转)Asp.net MVC 多语言问题的解决方案
    (转)SQL Server 2005 性能优化实战系列(文章索引)
    (转)结合领域驱动设计的SOA分布式软件架构
    (转)细说jquery ui和jqgrid的ASP.NET实现
    (转)简单代码生成器原理剖析
    (转)[翻译]ASP.NET MVC 3 开发的20个秘诀(十八)[20 Recipes for Programming MVC 3]:自动完成搜索
    sql优化: MySQL Explain详解
    mysql优化: show processlist 详解
  • 原文地址:https://www.cnblogs.com/xuxiaowei/p/14471469.html
Copyright © 2011-2022 走看看