乐趣区

关于前端:让弹窗更易于使用

题目又名:简略弹窗、多弹窗、简单弹窗怎么做代码和状态的解耦。

关键字:react / modal

问题

理论业务中,不乏弹窗组件中蕴含大量简单的业务逻辑。如:

function Order() {
    // 省略上百行办法状态
    const [visible,setVisible] = useState(false)
    const withModalState = useState<any>()
    
    return (
        <Modal>
            <Input/>
            <Input/>
            <Select/>
            <Checkbox/>
        </Modal>
    ) 
}

甚至还有多弹窗的情景。如:

function Order() {
    // 省略上百行办法状态
    const [visible1,setVisible1] = useState(false)
    const [visible2,setVisible2] = useState(false)
    const [visible3,setVisible3] = useState(false)
    
    const withModalState1 = useState<any>()
    const withModalState2 = useState<any>()
    const withModalState3 = useState<any>()
    
    // 省略 不懂多少 handlexx
    return (
        <main>
            ...
            <Modal1></* 省略很多代码 */></Modal1>
            <Modal2></* 省略很多代码 */></Modal3>
            <Modal3></* 省略很多代码 */></Modal3>
        </main>
    ) 
}
​

十分的痛:

  1. 如果弹窗在解决完外部流程后,又还有返回值,这有又会有一大通的处理函数。
  2. 如果这些代码都写在一个文件中还是不太容易保护的。

而且随着业务的断增长,每次这么体验很差。

冀望的应用形式

因而有没有一种更贴近业务理论的计划。

让弹窗只 专一于本人的外部 事务,同时又能将 控制权交给调用方 呢。

或者说我就是不喜爱 Modal 代码堆在一起……

如下:

// Modal1.tsx
export function Modal1(props) return <Modal></* ... */></Modal>

// 甚至能够将 MOdal 中的逻辑做的更聚合。通过 2 次封再导出给各方应用
export const function Check_XXX_Window() {/* */ return open(Modal1)}
export const function Check_XXX_By_Id_Window() { return open(Modal1)}
export const function Check_XXX_Of_Ohter_Window() { return open(Modal1)}

// Order.tsx
function Order() {

    function xxHndanle {const expect = Check_XXX_Window(Modal1,args) // 调用办法,传入参数,取得预期值,实现 1 个流程
    }
    return (
        <main>
            ...
            // 不理论挂载 Modal 组件
        </main>
    ) 
}

像这样拆散两者的代码,这样解决起来必定是清新很多的。

实现思路

实现的思路都是统一的。

  1. 创立占位符组件,放到利用的某处。
  2. 将相干状态集治理,并与 Modal 做好关联。
  3. 裸露控制权。

因而基于不同的状态治理计划,实现是多种多样的。置信很多大佬都本人外部封装过不少了。

然而在此基础上,我还想要 3 点。

  1. API 应用简略,但也容许肯定配置。
  2. 返回值类型推导,除了帮我治理 close 和 open 还要让我用起来带提醒的。
  3. 无入侵性,不依赖框架以外的货色。

ez-modal-react

emm…… 苦于市面上找不到这类产品(感觉同类并不多……探讨的也不多?)

于是我本人开源了一个。回应上文实现思路,能够点击看代码,几百行而已。

并不是突发奇想而来,其实相干个性早就在企业外部是应用多年了。我也是受前辈和社区启发。

根本个性

  1. 基于 Promise 封装
  2. 返回值类型推导
  3. 没有入侵性,体积小。

应用画面

import EasyModal, {InnerModalProps} from 'ez-modal-react';

+ interface IProps extends InnerModalProps<'fybe?'> /* 传入返回值类型 */ {
+   age: number;
+   name: string;
+ }

export const InfoModal = EasyModal.create(+ (props: Props) => {
  return (
    <Modal
      title="Hello"
      open={props.visible}
      onOk={() => {+       props.hide(); // warn 应有 1 个参数,但取得 0 个。(property) hide: (result: "fybe?") => void ts(2554)
      }}
      onCancel={() => {props.hide(null); //safe hide 承受 null 作为参数。它兼具 hide resolve 两种性能。}}
    >
      <h1>{props.age}</h1>
    </Modal>
  );
});

+ // warn 类型 "{name: string;}" 中短少属性 "age",但类型 "ModalProps<Props,"fybe?">" 中须要该属性。EasyModal.show(InfoModal, { name: 'foo'}).then((resolve) => {console.log(resolve);
+ // 输入 "fybe?" 
});

也反对用 hook

import EasyModal, {useModal, InnerModalProps} from 'ez-modal-react';

interface IProps extends InnerModalProps<'苏振华'>/* 指定返回值类型 */ {
  age: number;
  name: string;
}

export const Info = EasyModal.create((props: Props) => {const modal = useModal<Props>(); 

  function handleOk(){modal.hide(); // ts(2554) (property) hide: (result: "苏振华") => void ts(2554)
  } 

  return  <Modal open={modal.visible} onOk={handleOk} onCancel={modal.hide}></Modal>
});


EasyModal.show(Info,{age:18,}) // 短少属性 "age"

还有一些个性如反对配置 hide 弹窗时的默认行为。(我认为大多数状况下可能用不上)


export const Info = EasyModal.create((props: Props) => {const modal = useModal<Props>(); 

  function handleOk(){modal.hide(); 
+     modal.resolve('苏振华') // 须要手动抛出胜利
+     modal.remove() // 须要手动登记组件。可用于重复关上弹窗,然而不心愿状态被革除的场景。} 

  return  <Modal open={modal.visible} onOk={handleOk} onCancel={modal.hide}></Modal>

// Ohter.tsx
EasyModal.open(Info, {},
+  config:{
+    resolveOnHide:false, // 默认为 true
+    removeOnHide:false,  // 默认为 true
+  }
);

当然以上是针对弹窗内有简单业务场景的情况。

大部分场景都是调用方只在乎 open 或 close,仅仅解耦代码这一项益处,就能够让代码变得清新。

如罕用的有展现类,设置类的弹窗,TS 类型都用不上。

仓库

其余就不一一介绍了,次要的曾经说完了,想理解更多,能够看看仓库。github

🎮 Codesandbox Demo

Codesandbox 是一个线上集成环境,能够间接关上玩玩。点击 Demo Link 返回

初衷

让弹窗应用更轻松。

包名 ez 结尾,是因为我 DOTA 在东南亚打多了,感觉该词特地贴切。

授之于鱼叉

GitHub 仓库地址
:ez-modal-react

感觉有用帮我点个星 \~\~\~ 感恩,有啥问题能够提出,看到会回复。如果有须要会继续保护该我的项目。

退出移动版