Ant Design 的Bug修复示例详解

目录
  • 引言
  • 第一步、选择要修复的Bug
  • 第二步、准备工作
  • 第三步、问题排查
  • 第四步、问题修复
  • 第五步、单元测试
  • 第六步、提交Pull Request
  • 总结

引言

我在工作中大量使用Ant Design,它为我省去了很多重复劳动,所以有空的时候,我也会为Ant Design做一些微小的贡献。

本文详细描述了我处理一个Ant Design的Bug全过程,文章内容较多但难度并不高,新手同学看完也可以尝试为Ant Design添砖加瓦!

第一步、选择要修复的Bug

Ant Design有不少Bug,你可以直接访问它的Issues,挑一个简单的问题尝试解决,需要注意的是,并不是所以Issue都是Bug,经过管理员确认过的Bug一般会打上Bug的标记。

这次我处理的问题是#37165

第二步、准备工作

Fork ant-design仓库到自己的Github,回到自己的Github,将刚刚Fork的仓库克隆到本地,然后基于master分支新建一个bugfix分支,接着安装依赖,启动项目,然后就可以在开发环境访问Ant Design官网上所有的Demo,方便调试。

npm install && npm run start

第三步、问题排查

回到问题#37165,它的表现是:一个DatePicker,一个Input, 用户用鼠标选中Input的内容进行复制时经常会滑到DatePicker,会触发日历控件输入框的focus事件。

这种操作是比较常见的,问题简化完了就是:只要在日历控件上触发mouseUp就会打开日历控件。

查看官网Demo发现确实存在这个问题,第一反应是日历控件的输入框绑定了onMouseUp事件,查看对应的DatePicker组件源码,定位到文件ant-design/components/date-picker/generatePicker/generateSinglePicker.tsx第121~156行

(基于antd@4.23.4版本,不同版本行数可能不同):

import RCPicker from 'rc-picker';
// 中间代码省略……
<RCPicker<DateType>
  ref={innerRef}
  placeholder={getPlaceholder(mergedPicker, locale, placeholder)}
  suffixIcon={suffixNode}
  dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
  dropdownClassName={popupClassName || dropdownClassName}
  clearIcon={<CloseCircleFilled />}
  prevIcon={<span className={`${prefixCls}-prev-icon`} />}
  nextIcon={<span className={`${prefixCls}-next-icon`} />}
  superPrevIcon={<span className={`${prefixCls}-super-prev-icon`} />}
  superNextIcon={<span className={`${prefixCls}-super-next-icon`} />}
  allowClear
  transitionName={`${rootPrefixCls}-slide-up`}
  {...additionalProps}
  {...restProps}
  {...additionalOverrideProps}
  locale={locale!.lang}
  className={classNames(
    {
      [`${prefixCls}-${mergedSize}`]: mergedSize,
      [`${prefixCls}-borderless`]: !bordered,
    },
    getStatusClassNames(
      prefixCls as string,
      getMergedStatus(contextStatus, customStatus),
      hasFeedback,
    ),
    className,
  )}
  prefixCls={prefixCls}
  getPopupContainer={customizeGetPopupContainer || getPopupContainer}
  generateConfig={generateConfig}
  components={Components}
  direction={direction}
  disabled={mergedDisabled}
/>

以上源码没有传入onMouseUp,将解构赋值prop的{...restProps}注释掉,查看本地Demo,问题依然存在,说明restProps也没有传入onMouseUp

由于DatePicker组件是基于RCPicker封装的,接下来继续深入RCPicker组件,看看onMouseUp是不是在RCPicker里面绑定的。

rc-pickerreact-components组件库中的日历组件,Ant Design大部分组件都是在react-components基础上封装的。

查看rc-picker源码,rc-picker默认导出的是Picker组件:

import Picker from './Picker';
//...
export default Picker;

定位到picker/src/Picker.tsx,搜索字符串"onMouseUp",发现在日历控件输入框的父级div绑定了onMouseUp事件,对应的回调函数在287行(基于rc-picker@2.6.10):

// 输入框父级元素 L530~L555
<div
  ref={containerRef}
  className={classNames(prefixCls, className, {
    [`${prefixCls}-disabled`]: disabled,
    [`${prefixCls}-focused`]: focused,
    [`${prefixCls}-rtl`]: direction === 'rtl',
  })}
  style={style}
  onMouseDown={onMouseDown}
  // 看这里
  onMouseUp={onInternalMouseUp}
  onMouseEnter={onMouseEnter}
  onMouseLeave={onMouseLeave}
  onContextMenu={onContextMenu}
  // 顺便关注一下这里,后文会说
  onClick={onClick}
>
  <div
    className={classNames(`${prefixCls}-input`, {
      [`${prefixCls}-input-placeholder`]: !!hoverValue,
    })}
    ref={inputDivRef}
  >
    {inputNode}
    {suffixNode}
    {clearNode}
  </div>
</div>
// onMouseUp回调 L287~L296
const onInternalMouseUp: React.MouseEventHandler<HTMLDivElement> = (...args) => {
  if (onMouseUp) {
    onMouseUp(...args);
  }
  // 问题就在这里
  if (inputRef.current) {
    inputRef.current.focus();
    triggerOpen(true);
  }
};

就在函数onInternalMouseUp中,除了触发onMouseUp,还触发了输入框的focus事件!

if (inputRef.current) {
  inputRef.current.focus();
  triggerOpen(true);
}

此时,应该弄清楚一件事:当时为什么要写这几行代码?

最好的途径就是看看当时的commit message,为了方便后续调试,还是将rc-picker仓库克隆到本地:先Fork,再新建分支,然后安装依赖,启动项目。

PS:VSCode安装GitLens插件,即可查看每一行代码的commit记录。

从这几行代码对应的commit了解到,这几行代码是为了解决Ant Design的日历控件点击输入框右侧的icon没有弹出日历面板的问题。

知道它的作用了,已经成功了一半!看看要怎么修复?

第四步、问题修复

到这一步,建议先到对应的Issue下面留言说明正在处理中,避免其他开发者再花时间修复同一个问题。

接着,要解决2个问题:

  • 点击日历控件输入框右侧的icon需要打开日历面板
  • 不要用mouseUp事件来打开,想想其它实现方式

答案显而易见了,那就是改成在onClick里触发,因为icon节点同样被输入框的父级包裹,icon的click事件必然会冒泡到父级,从而触发父级的onClick。

查看以上源码发现,输入框的父级已经有一个onClick属性,只需要将以上的4行代码挪到onClick的回调即可,点击这里查看详细修改。

修改完成,查看本地Demo,问题已经解决了,胜利在望!

第五步、单元测试

原来的commit写了对应的单元测试,我们修改了它的实现,同时也需要修改对应的单元测试:

// picker/tests/picker.spec.tsx L620~631
it('Picker should open when click inside', () => {
  const onClick = jest.fn();
  const wrapper = mount(<MomentPicker onClick={onClick} />);
  const inputElement = wrapper.find('input').instance() as any as HTMLInputElement;
  inputElement.focus = jest.fn();
  wrapper.find('.rc-picker').simulate('click');
  expect(inputElement.focus).toHaveBeenCalled();
  expect(wrapper.isOpen()).toBeTruthy();
  expect(onClick).toHaveBeenCalled();
});

修改完成之后,完整地跑一遍单元测试:

npm run test

确保所有单元测试都通过

Test Suites: 8 passed, 8 total
Tests:       294 passed, 294 total
Snapshots:   11 passed, 11 total
Time:        15.643s

代码部分到这里就算圆满完成了!

第六步、提交Pull Request

这一步,是本文最简单的一步了!

提交代码,push到远程仓库,打开仓库页面,会看到页面上出现了一个【compare & pull request】的入口,点击即可向Ant Design创建合并请求,输入修复的Issue链接(这个很重要,到时候Issue页面会自动关联你的此次的pull request)和修复思路或理由,方便管理员review。

最后,等待管理员review,没问题的话管理员会合并分支,然后发布新版本,代码最终会应用到数十万项目中,Bug修复大功告成!

总结

最后,总结一下,第一次提交PR,建议选择简单的Issue,重要的是先将整个流程熟悉一遍,不要一开始就挑战复杂的问题,如果花了很长时间却解决不了问题,自信心受挫,可能就不想继续下去了。

以上就是Ant Design 的Bug修复示例详解的详细内容,更多关于Ant Design Bug修复的资料请关注我们其它相关文章!

(0)

相关推荐

  • AntDesignPro使用electron构建桌面应用示例详解

    目录 注意事项声明 主要分为两个部分 开发环境使用 打包应用配置 package.json配置打包后的路径方式 使用 electron-builder 打包 exe 文件或者安装包,压缩包 安装 package.json添加命令 (打包windows) 添加打包配置 执行打包命令 使用 electron-packager 打包成 exe 文件 执行命令 提示 注意事项声明 所有 node 包必须使用 npm 安装不可使用 cnpm, 使用 cnpm 安装的 node 包会导致打包时间无限可能 具

  • Ant Design 组件库按钮实现示例详解

    目录 1 antd 之 Button API 2 antd 之 Button 示例 1 antd 之 Button API antd 组件库是基于 Ant Design 设计体系的 React UI 组件库,antd 为 Web 应用提供了丰富的基础 UI 组件,可以用于研发企业级中后台产品.这篇咱们介绍 antd 组件库之 按钮. 按钮 Button 是一个比较基础的 UI 组件,一般在有交互的应用中都会用到. 其 DOM 节点为 <Button>...</Button>,ant

  • 前端开发使用Ant Design项目评价

    目录 好的方面 不好的方面 更新@2020 更新@2022 Tooltip 直接使用 rc-tooltip 的 props type 好的方面 作为前端开发使用 Ant Design 1年多了,想说几句. 先说好的方面—— 它提供的大量功能比较全面且UI风格统一的组件,能帮助开发者快速搭建通用场景下的应用界面.这大概是得益于蚂蚁金服业务线上极为广泛的应用场景,驱动了 Ant Design 团队通过对使用情况的观察汇总,整理出来了这么一个组件库.他们的经验积累如此之丰富,足以让这个库支持大部分其他

  • ant-design-vue动态表格合并案例

    目录 前言 数据格式 ant-desgin-vue表格提供的api 合并单元格算法实现 效果展示 前言 最近接到一个需求,要把后端传过来的数据动态展示在表格上面,并且支持前端筛选,相同数据进行单元格合并, 最终实现的效果如下: 数据格式 后端会返回给我们一个数组,数组的每一项格式是这样,在这个需求里,我们需要对 title,department,bugType 这三个字段相同的值的单元格进行合并 { fixCount: 0, id: 0, codeType: '新代码', bugType: 'u

  • 基于vue3+antDesign2+echarts 实现雷达图效果

    目录 右上角时间选择器的实现 五角雷达图的绘制及数据渲染 右上角时间选择器的实现 修改ant组件样式 根据原型图,该选择器为月份时间选择器,使用a-month-picker,但原始的月份选择器样式与设计图不符,需要进行修改,修改有分为两部分:1.选择框:2.额外弹出的日历 选择框样式修改 修改ant组件时应避免全局修改,如使用less语法,对ant组件的修改应在该页面的class下 <style lang="less" > @vw: 19.2vw; @vh: 10.8vh;

  • Ant Design 组件库之步骤条实现

    目录 引言 1 antd 之 Steps API 2 antd 之 Steps 示例 引言 antd 组件库是基于 Ant Design 设计体系的 React UI 组件库,antd 为 Web 应用提供了丰富的基础 UI 组件,可以用于研发企业级中后台产品.这篇咱们介绍 antd 组件库之 步骤条. 1 antd 之 Steps API 步骤条 Steps 的用处是在 当任务复杂或者存在先后关系时,将其分解成一系列的步骤,从而达到简化任务的目的.其 DOM 节点为 : <Steps> &l

  • Ant Design 的Bug修复示例详解

    目录 引言 第一步.选择要修复的Bug 第二步.准备工作 第三步.问题排查 第四步.问题修复 第五步.单元测试 第六步.提交Pull Request 总结 引言 我在工作中大量使用Ant Design,它为我省去了很多重复劳动,所以有空的时候,我也会为Ant Design做一些微小的贡献. 本文详细描述了我处理一个Ant Design的Bug全过程,文章内容较多但难度并不高,新手同学看完也可以尝试为Ant Design添砖加瓦! 第一步.选择要修复的Bug Ant Design有不少Bug,你可

  • RocketMQ实现随缘分BUG小功能示例详解

    目录 正文 实现过程 生产者: 正文 以前公司的产品已经上线20多年了,主要是维护,也就是改bug.每周我们Team会从Jira上拿我们可以改的bug,因为每个团队负责的业务范围不一样,我们团队只能改我们自己业务范围的.这样每周大概有20个左右的新bug,假如团队一共10个人,那么均分就是每人两个,改完下班. 但是这BUG肯定有难有简单,大家肯定都愿意改简单的,在家办公,任务量完了不就等于放假么.开始是自己给自己抢,就忒卷,是欧美项目,所以客服晚上报出来的bug多.有的哥们早上5点起来看有没有新

  • 比ant更丰富Modal组件功能实现示例详解

    目录 有哪些比ant更丰富的功能 render部分 渲染黑色蒙层 渲染弹框主体 设置body overflow:hiiden 有哪些比ant更丰富的功能 普通的modal组件如下: 我们写的modal额外支持,后面没有蒙版,并且Modal框能够拖拽 还支持渲染在文档流里,上面的都是fixed布局,我们这个正常渲染到文档下面: render部分 <RenderDialog {...restState} visible={visible} prefixCls={prefixCls} header={

  • echart实现大屏动效示例详解

    目录 1.通过dataZoom实现柱状图动态前移效果 2.叠加流光效果 3.柱状图光亮轮播 1.通过dataZoom实现柱状图动态前移效果 最近做大屏相关需求,产品说需要炫酷一点的效果,于是做了一些echart相关的动效 设置dataZoom当前缩放值,加定时器,实现轮播效果. 示例: option = { color: ['#1E90FF', '#FFA500'], tooltip: { trigger: 'axis', axisPointer: {} }, grid: { left: 20,

  • git hooks的作用及创建使用示例详解

    目录 1. 什么是git hooks ?有什么用啊? 1.1 是个啥 1.2 有啥用?我以前没用过它不也一样好好的吗?我干嘛要用它? 2. 怎么创建一个 git hooks ? 2.1 首先看git hooks存在哪里 2.2 创建一个pre-commit钩子 2.3 触发钩子 3 有用点的实战 4 总结 5 其他 5.1 如果在mac下报以下异常 5.2 常用钩子 5.3 hooks可以使用什么语言? 1. 什么是git hooks ?有什么用啊? 1.1 是个啥 git大家都在用吧,相信现在

  • webpack 5.68.0版本教程示例详解

    目录 起步 1. 基本安装 2. 配置出入口 plugin 1. html-webpack-plugin 2. progress-bar-webpack-plugin loader 1. css-loader与style-loader 2. url-loader与file-loader 3. sass-loader 4. postcss-loader 5. babel-loader 搭建环境 1. 开发环境与生产环境 2. 配置别名 代码分离 1. webpack-bundle-analyzer

  • 示例详解Python3 or Python2 两者之间的差异

    每门编程语言在发布更新之后,主要版本之间都会发生很大的变化. 在本文中,Vinodh Kumar 通过示例解释了 Python 2 和 Python 3 之间的一些重大差异,以帮助说明语言的变化. 本教程主要介绍内容: 表达式 Print 选项 Unequal 操作 Range 自动迁移 性能问题 主要的内部事务更改 1.表达式 在 Python 2 中为获得计算表达式,你会键入: 但在 Python 3 中,你会键入: 因此,无论我们输入什么,值都会分配给 2 和 3 中的变量 x.当在 Py

  • 为什么不推荐使用BeanUtils属性转换工具示例详解

    什么是BeanUtils工具 BeanUtils工具是一种方便我们对JavaBean进行操作的工具,是Apache组织下的产品. BeanUtils工具一般可以方便javaBean的哪些操作? 1)beanUtils 可以便于对javaBean的属性进行赋值. 2)beanUtils 可以便于对javaBean的对象进行赋值. 3)beanUtils可以将一个MAP集合的数据拷贝到一个javabean对象中. 1 背景 之前在专栏中讲过"不推荐使用属性拷贝工具",推荐直接定义转换类和方

  • C语言大厂面试技巧及strcpy()函数示例详解

    目录 1.什么是优秀的代码? 2.常见的coding技巧有哪些? 3.以模拟实现strcpy为例 (1)了解strcpy()函数 (2)正片开始(危) 1.第一阶段(面试官:最多5分) 2.第二阶段(面试官:最多7分) 3.第三阶段的代码:(面试官:最多8分) 4.第四阶段(面试官:完美代码!10分!) 1.什么是优秀的代码? 1. 代码运行正常 2. bug很少 3. 效率高 4. 可读性高 5. 可维护性高 6. 注释清晰 7. 文档齐全 2.常见的coding技巧有哪些? 1. 使用ass

  • Python实现双X轴双Y轴绘图的示例详解

    诈尸人口回归.这一年忙着灌水忙到头都掉了,最近在女朋友的提醒下终于想起来博客的账号密码,正好今天灌水的时候需要画一个双X轴双Y轴的图,研究了两小时终于用Py实现了.找资料的过程中没有发现有系统的文章,反正代码都整理出来了,我决定顺势水一篇. 目前找到的plt实现双X轴双Y轴绘图方式有两种: 使用fig.add_subplot方式将两对坐标系叠加在一个fig上实现双X轴双Y轴效果.所有调整均可完美实现,推荐该方式 通过axes.twinx().twiny()方式实现双X轴双Y轴图形绘制.问题在于对

随机推荐