前言
首先,让我们来看一看 Ant Design 官网的第一个关于 Modal
的 demo
1 | 复制代码import { Modal, Button } from 'antd'; |
当然,一般来说,我们写的 Modal
不会像官网里的例子这么的简单,毕竟这么简单的话会更倾向于使用类似于 Modal.confirm
等 API 直接调用弹出就好了。我们可能会对 Modal
进行二次封装,里面写一些代码逻辑及可能是固定的譬如 title
直接写在组件内,然后把一些像是 visible
、onOk
及 onCancel
这种 API 用 props
暴露出去。
这种把 visible
提升到父组件的方式固然能解决问题,可是这种方式也导致了一个问题。每次我们打开弹窗的时候,因为 visible
是在父组件中的状态,所以父组件也会重新 render
一次,甚至,如果父组件中的其他子组件没有做优化的话(没有使用 memo
或者没有设置 shouldComponentUpdate
),也会跟着重新 render
一次。
那么有没有什么方法可以解决这个问题呢?当然可以,我们只要把 visible
的状态留在和 Modal
有关的子组件里面就可以了。而在父组件中,其实我们所需要的只是 打开弹窗 以及 接收子组件的回调 两个需求。那么有哪些方式可以实现把 visible
留在子组件中呢?下面我们逐一介绍,因为我想不到什么命名,所以下面就一二三四了,emmm,就这样。
具体实现
在线代码
方案一
1 | 复制代码import React, { memo, useState } from "react"; |
第一种方案就是比较投机取巧,但是它也有它的缺点,就是打开弹窗这个操作只能由某一个元素完成且不能更多了。
方案二
对于在父组件中操作子组件状态这种事情,我们自然而然的就会想到使用 ref
,下面就让我们来看看要怎么用 ref
实现。
1 | 复制代码import React, { useState, useImperativeHandle, useRef } from "react"; |
使用 ref
的方式也很简单,这里我们将一些额外的参数使用 show
这个方法来传递,而不是像方案一中那样用 props
,但是我们使用时需要一个额外的变量来存储,只能说,这还不够完美。
方案三
对于在父组件中控制子组件这件事,我们当然可以使用“无所不能”的发布订阅,因为发布订阅并不是我们这里所要讲的内容,所以就简单的导个包吧,我们这里使用了 eventemitter3
。
1 | 复制代码import React, { memo, useState, useRef, useEffect } from "react"; |
在上面的代码中,因为直接把 eventEmitter
一起 export
出去会显得不那么优雅(不知道怎么描述的时候就用优雅就对了,大概)。而且还需要用的人知道,要调用 emit
方法触发 show
事件,实在是不优雅,所以我们直接在 Modal3
上绑定一个 show
方法来调用。
当看完上面的代码,我想应该有人会发现,其实我们根本就没有必要为此而引入一个 eventEmitter
,这实在是有一种杀鸡用了牛刀的感觉。我们为什么不直接在 useEffect
内把 handler
直接赋值给 Modal3.show
呢?于是,我们就有了方案四
方案四
1 | 复制代码import React, { memo, useState, useRef, useEffect } from "react"; |
更多思考
上面提到了好几种解决方法,其实我们还可以把状态进一步提升,使用 Context
来传递,在父组件中接收 show
这个不会变化的 API,在 Modal
所在的组件中接收会变化的 visible
以及 payload
,当然我觉得这样做过于复杂,所以没有列举。看到这里,我想大家也都知道,我肯定是最推荐方案四啦,之所以全都写出来,是为了告诉大家,我们应该有更多的思考,而不是用某一种方法解决了,就等于真正的掌握了。当然上面的都是我能想到的方法,当然也会有我想不到的,如果你想到了什么其他的方法,烦请赐教。
除此之外,我想留更多的问题给大家:
- 上面的代码中有很多可以复用的逻辑,那么如何复用?
- 我们可以发现,上面的实现都是无论
show
多少次都是同一个弹窗,那么有哪些方法可以实现类似于Modal.confirm
的效果呢? - Ant Design 中的
message
组件又该如何实现,更进一步的,如果要限制同事出现的 message 的数量,又该怎么做?
第一次写文章因为不太会表达,所以就贴了很多代码,求原谅,以后我会慢慢锻炼自己多写一些文字的。上面提到的问题,如果有需要,我也会逐一给大家解答,以更多文章的方式。
那么最后,如果觉得文章有用的话,就点个关注吧。
本文转载自: 掘金