欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Ant Design 的Bug修復(fù)示例詳解

 更新時(shí)間:2022年10月27日 15:39:28   作者:Undefined_w  
這篇文章主要為大家介紹了Ant Design 的Bug修復(fù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

我在工作中大量使用Ant Design,它為我省去了很多重復(fù)勞動(dòng),所以有空的時(shí)候,我也會(huì)為Ant Design做一些微小的貢獻(xiàn)。

本文詳細(xì)描述了我處理一個(gè)Ant Design的Bug全過(guò)程,文章內(nèi)容較多但難度并不高,新手同學(xué)看完也可以嘗試為Ant Design添磚加瓦!

第一步、選擇要修復(fù)的Bug

Ant Design有不少Bug,你可以直接訪問(wèn)它的Issues,挑一個(gè)簡(jiǎn)單的問(wèn)題嘗試解決,需要注意的是,并不是所以Issue都是Bug,經(jīng)過(guò)管理員確認(rèn)過(guò)的Bug一般會(huì)打上Bug的標(biāo)記。

這次我處理的問(wèn)題是#37165。

第二步、準(zhǔn)備工作

Fork ant-design倉(cāng)庫(kù)到自己的Github,回到自己的Github,將剛剛Fork的倉(cāng)庫(kù)克隆到本地,然后基于master分支新建一個(gè)bugfix分支,接著安裝依賴,啟動(dòng)項(xiàng)目,然后就可以在開(kāi)發(fā)環(huán)境訪問(wèn)Ant Design官網(wǎng)上所有的Demo,方便調(diào)試。

npm install && npm run start

第三步、問(wèn)題排查

回到問(wèn)題#37165,它的表現(xiàn)是:一個(gè)DatePicker,一個(gè)Input, 用戶用鼠標(biāo)選中Input的內(nèi)容進(jìn)行復(fù)制時(shí)經(jīng)常會(huì)滑到DatePicker,會(huì)觸發(fā)日歷控件輸入框的focus事件。

這種操作是比較常見(jiàn)的,問(wèn)題簡(jiǎn)化完了就是:只要在日歷控件上觸發(fā)mouseUp就會(huì)打開(kāi)日歷控件。

查看官網(wǎng)Demo發(fā)現(xiàn)確實(shí)存在這個(gè)問(wèn)題,第一反應(yīng)是日歷控件的輸入框綁定了onMouseUp事件,查看對(duì)應(yīng)的DatePicker組件源碼,定位到文件ant-design/components/date-picker/generatePicker/generateSinglePicker.tsx第121~156行

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

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}
/>

以上源碼沒(méi)有傳入onMouseUp,將解構(gòu)賦值prop的{...restProps}注釋掉,查看本地Demo,問(wèn)題依然存在,說(shuō)明restProps也沒(méi)有傳入onMouseUp

由于DatePicker組件是基于RCPicker封裝的,接下來(lái)繼續(xù)深入RCPicker組件,看看onMouseUp是不是在RCPicker里面綁定的。

rc-pickerreact-components組件庫(kù)中的日歷組件,Ant Design大部分組件都是在react-components基礎(chǔ)上封裝的。

查看rc-picker源碼,rc-picker默認(rèn)導(dǎo)出的是Picker組件:

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

定位到picker/src/Picker.tsx,搜索字符串"onMouseUp",發(fā)現(xiàn)在日歷控件輸入框的父級(jí)div綁定了onMouseUp事件,對(duì)應(yīng)的回調(diào)函數(shù)在287行(基于rc-picker@2.6.10):

// 輸入框父級(jí)元素 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}
  // 順便關(guān)注一下這里,后文會(huì)說(shuō)
  onClick={onClick}
>
  <div
    className={classNames(`${prefixCls}-input`, {
      [`${prefixCls}-input-placeholder`]: !!hoverValue,
    })}
    ref={inputDivRef}
  >
    {inputNode}
    {suffixNode}
    {clearNode}
  </div>
</div>
// onMouseUp回調(diào) L287~L296
const onInternalMouseUp: React.MouseEventHandler<HTMLDivElement> = (...args) => {
  if (onMouseUp) {
    onMouseUp(...args);
  }
  // 問(wèn)題就在這里
  if (inputRef.current) {
    inputRef.current.focus();
    triggerOpen(true);
  }
};

就在函數(shù)onInternalMouseUp中,除了觸發(fā)onMouseUp,還觸發(fā)了輸入框的focus事件!

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

此時(shí),應(yīng)該弄清楚一件事:當(dāng)時(shí)為什么要寫(xiě)這幾行代碼?

最好的途徑就是看看當(dāng)時(shí)的commit message,為了方便后續(xù)調(diào)試,還是將rc-picker倉(cāng)庫(kù)克隆到本地:先Fork,再新建分支,然后安裝依賴,啟動(dòng)項(xiàng)目。

PS:VSCode安裝GitLens插件,即可查看每一行代碼的commit記錄。

從這幾行代碼對(duì)應(yīng)的commit了解到,這幾行代碼是為了解決Ant Design的日歷控件點(diǎn)擊輸入框右側(cè)的icon沒(méi)有彈出日歷面板的問(wèn)題。

知道它的作用了,已經(jīng)成功了一半!看看要怎么修復(fù)?

第四步、問(wèn)題修復(fù)

到這一步,建議先到對(duì)應(yīng)的Issue下面留言說(shuō)明正在處理中,避免其他開(kāi)發(fā)者再花時(shí)間修復(fù)同一個(gè)問(wèn)題。

接著,要解決2個(gè)問(wèn)題:

  • 點(diǎn)擊日歷控件輸入框右側(cè)的icon需要打開(kāi)日歷面板
  • 不要用mouseUp事件來(lái)打開(kāi),想想其它實(shí)現(xiàn)方式

答案顯而易見(jiàn)了,那就是改成在onClick里觸發(fā),因?yàn)閕con節(jié)點(diǎn)同樣被輸入框的父級(jí)包裹,icon的click事件必然會(huì)冒泡到父級(jí),從而觸發(fā)父級(jí)的onClick。

查看以上源碼發(fā)現(xiàn),輸入框的父級(jí)已經(jīng)有一個(gè)onClick屬性,只需要將以上的4行代碼挪到onClick的回調(diào)即可,點(diǎn)擊這里查看詳細(xì)修改。

修改完成,查看本地Demo,問(wèn)題已經(jīng)解決了,勝利在望!

第五步、單元測(cè)試

原來(lái)的commit寫(xiě)了對(duì)應(yīng)的單元測(cè)試,我們修改了它的實(shí)現(xiàn),同時(shí)也需要修改對(duì)應(yīng)的單元測(cè)試:

// 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();
});

修改完成之后,完整地跑一遍單元測(cè)試:

npm run test

確保所有單元測(cè)試都通過(guò)

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

代碼部分到這里就算圓滿完成了!

第六步、提交Pull Request

這一步,是本文最簡(jiǎn)單的一步了!

提交代碼,push到遠(yuǎn)程倉(cāng)庫(kù),打開(kāi)倉(cāng)庫(kù)頁(yè)面,會(huì)看到頁(yè)面上出現(xiàn)了一個(gè)【compare & pull request】的入口,點(diǎn)擊即可向Ant Design創(chuàng)建合并請(qǐng)求,輸入修復(fù)的Issue鏈接(這個(gè)很重要,到時(shí)候Issue頁(yè)面會(huì)自動(dòng)關(guān)聯(lián)你的此次的pull request)和修復(fù)思路或理由,方便管理員review。

最后,等待管理員review,沒(méi)問(wèn)題的話管理員會(huì)合并分支,然后發(fā)布新版本,代碼最終會(huì)應(yīng)用到數(shù)十萬(wàn)項(xiàng)目中,Bug修復(fù)大功告成!

總結(jié)

最后,總結(jié)一下,第一次提交PR,建議選擇簡(jiǎn)單的Issue,重要的是先將整個(gè)流程熟悉一遍,不要一開(kāi)始就挑戰(zhàn)復(fù)雜的問(wèn)題,如果花了很長(zhǎng)時(shí)間卻解決不了問(wèn)題,自信心受挫,可能就不想繼續(xù)下去了。

以上就是Ant Design 的Bug修復(fù)示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Ant Design Bug修復(fù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論