​Ant Disign 4.0 升級實踐撲街指南 (一)

  • 2020 年 3 月 13 日
  • 筆記

背景

我們都知道, AntD 最近喜提了4.0, 更新了許多新特性,看的我是心花怒放, 喜不自勝。更貼心的是還提供了升級工具,看了一些文章介紹說能三分鐘升級。於是周六的時候, 懶覺我也不睡了, 跑到公司開始了升級之旅。

註:此篇文章僅是我個人升級的時候遇到的一些問題,不具代表性,僅供參考

正文

首先是從這篇文章開始的:

很多公眾號也轉發了這篇文章, 很吸引人, 我也想體驗一下。

撲街第一步: antd4-codemod

看官方介紹:

一鍵轉換!我滴龜龜, 也太好了吧!!

馬上安排!

於是我敲下了第一行命令:

sudo npm i -g @ant-design/codemod-v4

全局安裝了這個程式碼轉換工具, 很順利。

撲街第一步:antd4-codemod

運行 antd4-codemod src

控制台:

出師未捷身先死

問題不大, 我們老實人不怕這個。

缺少core-js, 那就裝一個。

安裝之後, 還是同樣的報錯。。。

一番搜索之後, 在一個不起眼的文章里找到了答案:

全局安裝, 果然不報錯core-js找不到了, 問題解決。

(中間也爆了其他的錯, 花了不少時間,不過都一一解決了。)

直到又爆了新的錯誤:

搜索到一些答案:

按照文章中的提示,逐個修改,等待安裝。

運行一下, 還是不行。。。

表情逐漸凝固。

這時候已經六七點了,看看外面, 天都黑了。

這第一步還沒邁出去, 開始暴躁。

我是誰, 我在哪,我為什麼要用這個 antd4-codemod...

冷靜一下, 打了局農藥單排,輸了。

然後開始手動一個個改文件。

撲街第二步: Form initialValues

想著今天一定, 至少, 得改完一個頁面看看。

就挑了個簡單的, 一個Form表單頁。

v3 與v4的表單差別還是挺大的。

Form v3 & v4

去除 Form.create

v4 的 Form 不再需要通過 Form.create() 創建上下文。Form 組件現在自帶數據域,因而 getFieldDecorator 也不再需要,直接寫入 Form.Item 即可:

// antd v3  const Demo = ({ form: { getFieldDecorator } }) => (    <Form>      <Form.Item>        {getFieldDecorator('username', {          rules: [{ required: true }],        })(<Input />)}      </Form.Item>    </Form>  );    const WrappedDemo = Form.create()(Demo);  複製程式碼

改成:

// antd v4  const Demo = () => (    <Form>      <Form.Item name="username" rules={[{ required: true }]}>        <Input />      </Form.Item>    </Form>  );

由於移除了 Form.create(),原本的 onFieldsChange 等方法移入 Form 中,通過 fields 對 Form 進行控制。

表單控制調整

Form 自帶表單控制實體,如需要調用 form 方法,可以通過 Form.useForm() 創建 Form 實體進行操作:

// antd v3  const Demo = ({ form: { setFieldsValue } }) => {    React.useEffect(() => {      setFieldsValue({        username: 'Bamboo',      });    }, []);      return (      <Form>        <Form.Item>          {getFieldDecorator('username', {            rules: [{ required: true }],          })(<Input />)}        </Form.Item>      </Form>    );  };    const WrappedDemo = Form.create()(Demo);

改成:

// antd v4  const Demo = () => {    const [form] = Form.useForm();      React.useEffect(() => {      form.setFieldsValue({        username: 'Bamboo',      });    }, []);      return (      <Form form={form}>        <Form.Item name="username" rules={[{ required: true }]}>          <Input />        </Form.Item>      </Form>    );  };

有個很簡單列表頁里包含一個Form,點擊按鈕,查看數據。

codeOpen鏈接:codepen.io/scaukk/pen/…

提了個issue: github.com/ant-design/…

這個問題,一個熱心網友說:

加一個effect 每次顯示modal的時候重置, 這個resetFields重置的每次都是initialValue的值 你每次確定的時候重置的值其實都是上一次的, 所以不會變

偏右的回復:

resetFields 是重置回 initialValues 的值,並且 initialValues 只用於第一次初始化,不響應後續的變化,你需要轉換一下思路:https://codepen.io/afc163-1472555193/pen/LYVjNWN?editors=0011

在官網中, 也找到了這樣的描述:

在 v3 版本中,修改未操作的欄位 initialValue 會同步更新欄位值,這是一個 BUG。但是由於被長期作為一個 feature 使用,因而我們一直沒有修復。在 v4 中,該 BUG 已被修復。initialValue 只有在初始化以及重置表單時生效。

所以, initialValue 只能作為組件初次掛載的時候生效。

偏右的做法和文檔推薦的一致:

render: (text, record) => (    <span onClick={() => {      setVisible(true)      setRecord(record)      form.setFieldsValue({        name: record.name,      });    }}>      <a>查看</a>    </span>  ),  複製程式碼

不過這樣子手動setFieldsValue比較麻煩, 我想了一下一下之後, 用了另一種方法是來解決這個問題。

新的辦法:

把 Modal 單獨抽出來, 把這裡的form:

const [form] = Form.useForm();

隨著組件的銷毀一起銷毀, 這樣每次的數據就都是新的了, 完美。

Live Demo:

至此, 第一個頁面就改完了。

結尾

後面還有好多個頁面需要改,不過我認為這是值得的。

之後還會持續更新, 希望大家都能避開這些點。

圖看不清楚的可以閱讀原文。

希望本文對大家有所幫助。