从Popconfirm的实现学习cloneElement用法

1,173 阅读2分钟

作为一名搬砖工程师,个人一直在使用antd(Ant Design),因为其丰富的组件库给管理后台开发带来了很多的便利性,里面也有很多实现方案值得借鉴,本文就以Popconfirm的实现做个介绍。

我们先看是如何使用的,下面是官方给出的例子:

import { Popconfirm, message } from 'antd';

function confirm(e) {
  console.log(e);
  message.success('Click on Yes');
}

function cancel(e) {
  console.log(e);
  message.error('Click on No');
}

ReactDOM.render(
  <Popconfirm
    title="Are you sure to delete this task?"
    onConfirm={confirm}
    onCancel={cancel}
    okText="Yes"
    cancelText="No"
  >
    <a href="#">Delete</a>
  </Popconfirm>,
  mountNode,
);

页面展示效果如下

image.png 我们查看上面代码实例,只是在a标签的外部包裹了一层Popconfirm组件,然而我们并没有定义a的点击事件,所有的配置直接放在了Popconfirm上,就能实现上述的功能。

在极其简单的使用方式上也能看出对代码的侵入型很小,如果那天我们不需要Popconfirm,直接将Popconfirm组件删除,并将onConfirm上的操作移到a的onClick上即可。

但是使用的时候就有一些疑问,a上面没有绑定任何的事件,但是点击的时候为什么会触发确认框呢?

所以就好奇翻了下源码,发现它的实现借助了React.cloneElement去实现的,该方法可以将元素拷贝并且修改其属性。

源码位置1:components/popconfirm

源码位置2:components/_util/reactNode.ts (基于React.cloneElement封装的工具函数)

我又看了先React的官方文档说明,React.cloneElement,其描述也简单明了

image.png

其实明白了这些,我们就能实现一些可插拔的组件了,例如antd中的下面组件

如果你深入使用antd的话,你会发现Form表单中Form.Item下面的input没有绑定value和onChange,但是为什么表单可以获得数据呢,其实也是通过React.cloneElement实现的。