likes
comments
collection
share

我看UI小姐姐就是在为难我这个切图仔

作者站长头像
站长
· 阅读数 20

前言

我正在参加「掘金·启航计划」,最近UI小姐姐不知道中了什么邪,要我把一个简单的表单,长这样

我看UI小姐姐就是在为难我这个切图仔

改成这个样子

我看UI小姐姐就是在为难我这个切图仔

咱也不懂啊,这样更好看了吗,只能照着改了,谁让我只是个卑微的切图仔呢.

我看UI小姐姐就是在为难我这个切图仔

实现过程

刚开始我觉得很简单嘛,封装一个组件,用它包裹表单元素,比如Input、 Select、DatePicker等,然后修改css样式,把表单元素的border干掉,给外面的组件加上border不就搞定了,看起来也不是很复杂的样子.第一版长这样

我看UI小姐姐就是在为难我这个切图仔

发现问题了嘛,select下拉选项的宽度和表单元素不一样长,当然我觉得问题不大能用就行,但是在ui眼里那可不行,必须要一样长,不然不好看. 好吧,在我的据理力争下,我妥协啦,开始研究下一版.

我看UI小姐姐就是在为难我这个切图仔

在第一版的基础上我发现只有Select有这个问题,那就好办了,针对它单独处理就行了,解决方法思考了3种:

  • 第一种就是antd的Select可以设置dropdownStyle,通过获取父元素的宽度来设置下拉菜单的宽度,以此达到等长的目的
  • 第二种就是通过设置label元素为绝对定位,同时设置Select的paddingLeft
  • 还有一种就是通过在Select里添加css伪元素(注意这种方法需要把content里的中文转成unicode编码,不然可能会乱码)

最终我采用的是第二种方法,具体代码如下

import React, { CSSProperties, PropsWithChildren, useMemo } from 'react';
import { Form, FormItemProps, Col } from 'antd';
import styles from './index.module.less';

interface IProps extends FormItemProps {
  label?: string;
  style?: CSSProperties;
  className?: string;
  isSelect?: boolean;
  noMargin?: boolean;
  col?: number;
}
export const WrapFormComponent = ({ children, className, isSelect, style, col, noMargin = true, ...props }: PropsWithChildren<IProps>) => {
  const labelWidth = useMemo(() => {
    if (!isSelect || !props.label) return 11;
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    context!.font = '12px PingFang SC';
    const metrics = context!.measureText(props.label);
    return metrics.width + (props.colon === undefined || props.colon ? 10 : 0) + 11;
  }, [isSelect, props.label, props.colon]);
  return (
    <Col span={col}>
      <Form.Item
        style={{ '--label-length': labelWidth + 'px', marginBottom: noMargin ? 0 : '16px', ...style } as CSSProperties}
        className={`${styles['wrap-form']} ${isSelect ? styles['wrap-form-select'] : ''} ${className || ''}`}
        {...props}
      >
        {children}
      </Form.Item>
    </Col>
  );
};

less代码

.wrap-form {
  padding: 0 !important;
  padding-left: 11px !important;
  border: 1px solid #c1c7cd;
  border-radius: 4px;

  :global {
    .ant-form-item-label {
      display: inline-flex !important;
      align-items: center !important;
    }

    .ant-form-item-label > label {
      height: auto;
      color: #919399;
      font-weight: 400;
    }

    .ant-picker {
      width: 100%;
    }

    .ant-input,
    .ant-select-selector,
    .ant-picker,
    .ant-input-number {
      border: none;
      border-color: transparent !important;
    }

    .ant-input-affix-wrapper {
      background: none;
      border: none;
    }
  }
}

.wrap-form-select {
  position: relative;
  padding: 0 !important;

  :global {
    .ant-form-item-label {
      position: absolute;
      top: 50%;
      left: 11px;
      z-index: 1;
      text-align: left;
      transform: translateY(-50%);
    }

    .ant-select-selector {
      padding-left: var(--label-length) !important;
    }

    .ant-select-selection-search {
      left: var(--label-length) !important;
    }

    .ant-select-multiple .ant-select-selection-search {
      top: -2px;
      left: 0 !important;
      margin-left: 0 !important;
    }

    .ant-select-multiple .ant-select-selection-placeholder {
      left: var(--label-length) !important;
      height: 28px;
      line-height: 28px;
    }
  }
}

最后就变成这样了,完美解决,这下ui总不能挑刺儿了吧.

我看UI小姐姐就是在为难我这个切图仔