前语
我正在参加「启航方案」,最近UI小姐姐不知道中了什么邪,要我把一个简略的表单,长这样
改成这个姿态
咱也不懂啊,这样更好看了吗,只能照着改了,谁让我仅仅个低微的切图仔呢.
完成进程
刚开端我觉得很简略嘛,封装一个组件,用它包裹表单元素,比如Input、 Select、DatePicker等,然后修正css款式,把表单元素的border干掉,给外面的组件加上border不就搞定了,看起来也不是很杂乱的姿态.第一版长这样
发现问题了嘛,select下拉选项的宽度和表单元素不一样长,当然我觉得问题不大能用就行,但是在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总不能挑刺儿了吧.