美文网首页
极简用法的RN弹窗-支持多层弹窗

极简用法的RN弹窗-支持多层弹窗

作者: wustzhy | 来源:发表于2024-01-08 19:25 被阅读0次

这篇,解决了上一篇超好用的react-native 弹窗容器遗留的2个痛点


Q: 代码调用一个弹窗的极简方式是怎样的?

A: 这样子👉🏻 XxModuleAlert.show({..})

为了这个极简用法的目标,我曾经 使用rn-global-modal封装过TextInputAlert,但依然有些问题或难用点,比如遮挡了Toast、更改mask颜色要改源码、布局上有些非正常的地方

因为不希望弹窗遮挡Toast,于是研究了react-native-root-toast,用的"react-native-root-siblings",从而找到了封装理想弹窗的更快的方式

于是,基于"react-native-root-siblings": "5.0.1",,造了一个 AlertManager

Why need AlertManager

相信大家使用过RN官方Modal的,都知道,iOS弹窗无法弹两个,使用起来不满足高内聚低耦合,难受。。。

RN官方Modal

  • 缺点:耦合过多!须visible属性,多1个import useState,多1行代码setVisble声明,弹窗组件须嵌入容器组件

rn-global-modal

  • 优点:函数式调起弹窗,任意处可调用
  • 缺点:iOS 不支持同时多层弹窗;toast的层级低于它 导致看不到/看不清

What AlertManager provide

  • 封装者:封装出高度解耦的弹窗。
  • 使用方:使用极简!

优势

  • vs Modal:去掉visible
  • vs rn-global-modal: 支持多层弹窗, TextInput弹窗对键盘支持更好??

How to use AlertManager

  • 使用方:
XxModuleAlert.show({...});
XxModuleAlert.hide();
  • 封装方:
class XxModuleAlert {
  static show() {
    AlertManager.show(<XxModuleView />, {
      key: XxModuleView.name,
    });
  }
  static hide() {
    AlertManager.hide(XxModuleView.name);
  }
}

export XxModuleAlert

const XxModuleView = () => {
    ...
    return (...)
}

源码

import React from "react";
import { Dimensions, TouchableOpacity, View } from "react-native";
import RootSiblingsManager from "react-native-root-siblings";

const { width, height } = Dimensions.get("window");

/**
 * 弹窗管理类
 * - 支持同时弹出多个弹窗 (Modal、rn-global-modal 不支持)
 * - 不会遮挡Toast(Modal、rn-global-modal 会遮挡Toast)
 */
class AlertManger {
  static _alertNodes = {}; // { key1: { rootNode: <A/>, onClose: () => {} }, key2: { rootNode: <B/>, onClose: () => {} }

  /**
   * 展示弹窗
   * @param {*} modalView             弹窗内所要展示的内容组件
   * @param {*} options.key                **必传** 弹窗唯一标识
   * @param {*} options.maskStyle          蒙层样式 默认值:{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }
   * @param {*} options.maskTouchClosable  弹窗蒙层是否可点击关闭
   * @param {*} options.closedCallback     弹窗关闭的回调
   * @param {*} options.animationType      [todo] 弹窗动画类型: none | fade | slide-up
   */
  static show(modalView, options) {
    const { key, maskTouchClosable, closedCallback, maskStyle } = options;

    let rootNode;
    const onClose = () => {
      rootNode?.destroy();
      rootNode = null;
      closedCallback?.();
    };
    rootNode = new RootSiblingsManager(
      (
        <View
          style={[
            {
              position: "absolute",
              width: width,
              height: height,
              justifyContent: "center",
              alignItems: "center",
              backgroundColor: "rgba(0,0,0,0.5)",
            },
            maskStyle,
          ]}
        >
          <TouchableOpacity
            style={{
              position: "absolute",
              width: width,
              height: height,
            }}
            activeOpacity={1}
            onPress={(e) => {
              maskTouchClosable && this.hide(key);
            }}
          />
          {modalView}
        </View>
      )
    );
    this._alertNodes[key] = { rootNode, onClose };

    console.log("this._alertNodes:::", this._alertNodes);
  }

  static hide(key) {
    console.log(
      "this._alertNodes?.[key]?.onClose::",
      this._alertNodes?.[key]?.onClose
    );
    this._alertNodes?.[key]?.onClose?.();
    delete this._alertNodes[key];
  }
}

export default AlertManger;

/* ----------------------- Usage ---------------------- */
/*
 * 弹窗开发者 这样封装自己的弹窗
    ```
    import AlertManager from "app/components/dialog/AlertManager.js";
    class BbModuleAlert {
      static show() {
        AlertManager.show(<BModuleView />, {
          key: BModuleView.name,
          maskTouchClosable: true,
          closedCallback: () => {
            console.log("BModuleView closedCallback");
          },
        });
      }
      static hide() {
        AlertManager.hide(BModuleView.name);
      }
    }

    export default BbModuleAlert;

    const BModuleView = () => {
      return (
        ...
      )
    }
    ```
*/

/*
 * 弹窗调用者 这样调用弹窗
    ```
    import BbModuleAlert from "./BbModuleAlert";
    BbModuleAlert.show();
    BbModuleAlert.hide();
    ```
*/

todo

  • 如何提供 页面级别的弹窗 showInComp(comp)

需求
某个弹窗,是当前A页面的子视图,若点击该弹窗种的按钮,跳转到下一个B页面时,该弹窗继续展示在A页面,B页面在最上层展示(是盖住该弹窗的)

  • 像 取消&确认 弹窗,可以基于这个重做一遍了

相关文章

  • uniapp 常用弹窗

    action-sheet 弹窗 alert 弹窗 confirm 弹窗 loading 弹窗 toast 弹窗

  • (功能测试合集)弹出窗口的常用测试点

    弹窗的类型弹窗的操作集合弹窗加载和展示弹窗的元素弹窗的属性弹窗的兼容性弹窗的风险参考文献 前言手机App弹窗是目前...

  • RN-底部弹窗

    介绍一款弹窗方法: 导入 import ActionSheet from 'react-native-action...

  • Appium-处理系统弹窗

    前言: 最近在搞appium自动化,iOS的系统弹窗是大家都会遇到的,本文来总结处理这种弹窗的用法。 环境: Ma...

  • 3个步骤彻底清除电脑广告弹窗!!

    你是否也被电脑广告、弹窗烦到炸裂? 腾讯QQ弹窗!搜狗输入法弹窗!搜狐新闻弹窗!网页广告弹窗!360资讯弹窗!!一...

  • 开发中Dialog弹窗优先级控制

    如果你的APP有多种弹窗,试想一下,你的APP中有(活动弹窗、登录弹窗、更新弹窗、alert弹窗...)它们出现的...

  • iOS原生弹窗UIAlertController

    越努力,越幸运 原生弹窗 iOS中可用UIAlertController快捷创建上面场景中的弹窗: 本文发布 简书...

  • PopView

    底部弹窗 中间弹窗

  • ionicPopup

    Ionic弹窗服务允许程序创建、显示弹出窗口,需要用户继续响应。弹窗系统支持更多灵活的构建alert(),prom...

  • UI设计师需要了解的 APP弹窗体系

    弹窗的定义 弹窗分为模态弹窗和非模态弹窗两种。 模态弹窗:很容易打断用户的操作行为,用户必须回应,否则不能进行其他...

网友评论

      本文标题:极简用法的RN弹窗-支持多层弹窗

      本文链接:https://www.haomeiwen.com/subject/xphondtx.html