美文网首页
Ant-design踩坑

Ant-design踩坑

作者: liuniansilence | 来源:发表于2020-01-10 18:11 被阅读0次

    Antd.Form

    踩坑
    1. 经过getFieldDecorator的注册后,所以的onChange函数会被接管。本身的onChange可能会失效。

    2. 如果getFieldDecorator包裹的content包含多个child,要注意封装成一个组件,不要直接在content里用Fragment包裹多个节点,可能有隐患埋坑。如果希望包裹一个或多个组件,需要单独额外去封装一个组件来,会增加文件层级,繁琐!

    3. 自定义的validator,要注意函数里关于value的前置校验,如果没有在validateFields的option配置里设置option.first = true,校验规则会依次校验下去,这个时候如果value == undefined,可能会导致validator里的value校验规则报jsError错误,因为没有try catch过,这个错误被吃掉,外部的form.validateFields也不会有任何反应。

    4. 经过getFieldDecorator注册过后的item,会丢失defaultValuevalue的属性,想要赋值预设值,必须通知getFieldDecorator时候传入option.initialValue进行预设值;

    优化方案

    使用antd的Form组件以及Form.Item来进行组件的包装和展示,表单管理采用外部库formik来控制,formik可以支持表单项的定义、展示、校验,formik本身暴露了api可以引入外部的校验库来做校验,官方推荐接入Yup来做检验管理。

    formik本身是一个与view层无关的纯model层的表单库,我们可以将表单的校验结果与Form.Item结合,来控制错误提示。

    Antd.Drawer

    使用了antd的抽屉组件,想在抽屉展开时,调用接口动态加载数据。目前在抽屉组件<Drawer>里包裹了一个目录菜单组件<Tree>,然后在<Tree>组件内部通过副作用hook(useEffect)去发起请求。但是发现每次展开时,抽屉都会卡顿。请求的时间每次大概300ms左右。

    看了github里,有人提了issue,但是问题并没有被解决就被关闭了。有个人提出了一个治标不治本的方案,如下:
    解决方案
    我通过使用一个hook来控制,使得在drawer动画完成后才显示容器内的内容,hook的代码如下:

    /**
     * Drawer 可见性
     */
    export const useDrawerVisible = timeout => {
      /** drawer 可见性 */
      const [visible, setVisible] = useState(false);
      /** 内容可见性 */
      const [contentVisible, setContentVisible] = useState(false);
      const open = () => {
        setVisible(true);
        setTimeout(() => setContentVisible(true), timeout);
      };
      const close = () => {
        setVisible(false);
        setContentVisible(false);
      };
      return {drawerVisible: visible, contentVisible, open, close};
    };
    
    
    const DrawerButton = () => {
      /** 抽屉可见性 */
      const {drawerVisible, contentVisible, open, close} = useDrawerVisible(350);
    
      return (
          <div>
            <a onClick={open}>
              点击显示Drawer
            </a>
            <Drawer
                width="700px"
                visible={drawerVisible}
                onClose={close}
            >
              {contentVisible &&
              <div>
                Drawer容器内的内容
              </div>}
            </Drawer>
          </div>
      );
    };
    

    这里的 timeout 设置为 350ms 是我猜想 Drawer 的动画时间应该在 350ms 左右

    Antd.Layout

    Layout下有Layout.Sider,layout本身有个props叫hasSIder: boolean。

    // Layout.tsx
    const classString = classNames(
        prefixCls,
        {
          [`${prefixCls}-has-sider`]: typeof hasSider === 'boolean' ? hasSider : siders.length > 0,
          [`${prefixCls}-rtl`]: direction === 'rtl',
        },
        className,
      );
    
    // 对应的样式
     &&-has-sider {
        flex-direction: row;
        > .@{layout-prefix-cls},
        > .@{layout-prefix-cls}-content {
          overflow-x: hidden;
        }
      }
    

    ${prefixCls}-has-sider这个class的出现与否由hasSider 和siders决定,siders的addSider和removeSider事件是在layout的context里取的。

    // Layout.tsx
     <LayoutContext.Provider
          value={{
            siderHook: {
              addSider: (id: string) => {
                setSiders(prev => [...prev, id]);
              },
              removeSider: (id: string) => {
                setSiders(prev => prev.filter(currentId => currentId !== id));
              },
            },
          }}
        >
          <Tag className={classString} {...others}>
            {children}
          </Tag>
        </LayoutContext.Provider>
    

    所以当sider外部没有报过layout的时候,切换页面时候,sider的removeSider事件触发失败,导致${prefixCls}-has-siderclass的计算出问题,进而影响了css样式。

    表现为:
    在A页面左右布局正常,到了B页面可能有sider外部没有layout,本来的左右布局混乱了变成了上下布局。但是切回A页面后,依旧不能正常左右,还展示了错误的上下。

    解决方法:
    给sider的外部套上layout。

    <Layout>
        <Layout.Sider theme="light" width="160">
            <LayoutMenu />
        </Layout.Sider>
        <Content />
    </Layout>
    

    相关文章

      网友评论

          本文标题:Ant-design踩坑

          本文链接:https://www.haomeiwen.com/subject/oidmactx.html