升级material-ui v4 to v5

material ui 已经升级到 v5啦。正好因为一个calendar的需求,赶上了这趟车。原因是calendar在选了年份后,可以自动展示月份。这个功能在v4 和 相关的库material-ui-pickers 都没有,翻了翻 material-ui-pickers的issue

 

发现这个库已经不在维护咯,啊这.....

 

 

从时间来看,2020年11月就已经不再维护。但是直到2022年2月份,我们才开始更新。说明这个库满足基础的date 业务是没问题。如何需要更丰富的交互和功能,就只能升级到v5。

接下来是我升级到v5 过程中遇到的问题和解决方法。提前告知一下,我们的项目已经安然无恙的使用上v5啦,撒花🎉

升级攻略 

 1. mui 的官方是提供了升级方案的,具体可以访问 https://mui.com/guides/migration-v4/ 

 2. 首先是删除掉原来的material-ui v4的依赖,然后再安装v5的依赖

 3. 依赖安装完以后,就执行官方提供的三个codemods, 快速替换原来的v4 component的引用地址和一些默认属性。

  • npx @mui/codemod v5.0.0/preset-safe ./
  • npx @mui/codemod v5.0.0/variant-prop ./
  • npx @mui/codemod v5.0.0/link-underline-hover ./

 

上面两个图是跑单个codemod后,扫描到要替换的文件,得半个多小时,要一个个换,得吐血....

4. 如果你也是ts的用户,那么上面的run完以后,yarn tsc。有问题就一个一个解决

5. 接下来就是style了。这个我花的时候最长.......

  • 根据codemods, 可以不改变原有写法的情况下将v4的style通过adaptV4Theme兼容到v5,就是有些warning,不过在一开始,是要保证升级完成,所以warning可以在升级结束后再去改,替换一下写法,这个文档中有提到
  •  然后就是挨个检查一下你正在使用的组件的交互和样式。

    • v5有的组件默认属性和交互会点点不同,比如snackbar, 现在默认是弹在页面的左下角,但是我们使用一般是在底部居中
    • 组件颜色值,这个可以找到对应的class,然后在theme 文件去全局修改
  • date picker
    • 更新前务必与UX沟通好,v5的date picker 和 material-ui-pickers的交互和样式有很大不同,这个需要她们确认好,否则更新完后UX和客户沟通,客户不接受就白白浪费时间啦
    • 此外v5的date picker和material-ui-pickers的逻辑也不一样,因此原来的一些配置需要一个一个的检查和修改
    • 问题
      • 在更新到v5的datePicker中,遇到几个问题,如下
      • datePicker: 例如:你选择了2022年,然后input框显示2022/3/19,然后你点了页面一下,input框的日期被清空了。这就是问题,它只会存selected的日期。虽然你选择了年份,但是月份和日期没有选,就没有存。这个官方已经在修了,等等吧。by the way, 官方每个周都会release一次,所以更新和修复bug的速度还是挺快的。https://github.com/mui/material-ui/releases
      • 测试:datePicker change事件没有触发
        • 原因:datePicker 是一个responsive的date组件,默认情况下,datePicker是moible模式
        • 解决:
          1. 方案一:jest.mock('@mui/lab/DatePicker', () => { return jest.requireActual('@mui/lab/DesktopDatePicker') })
          2. 方案二:
            beforeEach(() => {
                // add window.matchMedia
                // this is necessary for the date picker to be rendered in desktop mode.
                // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior
            Object.defineProperty(window,'matchMedia',{
                    writable: true,
            value: (query: string): MediaQueryList => ({
                        media: query,
            // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device
                        matches: query === '(pointer: fine)',
            onchange: () => {},
            addEventListener: () => {},
            removeEventListener: () => {},
            addListener: () => {},
            removeListener: () => {},
            dispatchEvent: () => false,
            }),
            });
            });
            
            afterEach(() => {
                // @ts-expect-error
                deletewindow.matchMedia;
            });

            这个方面是通过全局的方式, 设置matchMedia为deskTop的方式。从而触发datePicker的change事件

          3. 以上两种方案都是模拟它是desktop模式的测试,具体可以参考: https://github.com/mui/material-ui/issues/27038

 相关依赖:

  升级前最后看一下与material-ui相关的库,因为一旦material-ui升级,一般是会影响被依赖的第三方库的,比如:

    1. material-ui-phone-number. 还好这个库的dev已经升级到V3来支持material ui v5

    2. 本来material-ui-pickers是不需要被替换的,毕竟是单独引入的。但是它依赖的是material-ui v4。所以一旦升级,就一定会把它也换掉

 

其他:

  如果你使用了storybook, 记得一定要在.storybook下的main.js增加一个配置. 这样theme文件才会生效。

  因为mui v5默认样式emotion style。 因此需要将其关掉,用我们自己配置的theme

features: {
    emotionAlias:false,
},

 

posted @ 2022-03-20 12:41  巫瞅瞅  阅读(557)  评论(0)    收藏  举报