allowClear 原理
- 显示清除按钮:Ant Design 在
Select
组件中内置了一个ClearOutlined
图标,并通过 CSS 控制其显示与隐藏。 - 清除操作:点击清除按钮后,
Select
组件会调用onChange
回调函数,并将参数设为undefined
(或空字符串''
),以此来清除已选中的值。
allowClear 简化版源码
import React from 'react';
import PropTypes from 'prop-types';
class Select extends React.Component {
// 构造函数
constructor(props) {
super(props);
this.state = {
// 是否显示下拉菜单
dropdownVisible: false,
// 选中的值
selectedValue: props.value || null,
};
}
// 清除选中值
handleClear = () => {
this.setState({
selectedValue: null,
});
// 触发 onChange 事件,将选中值传递为 null
this.triggerChange(null);
};
// 处理选中值变化
handleChange = (value) => {
this.setState({
selectedValue: value,
});
// 触发 onChange 事件,将选中值传递出去
this.triggerChange(value);
};
// 触发 onChange 事件
triggerChange = (changedValue) => {
const { onChange } = this.props;
if (onChange) {
onChange(changedValue);
}
};
// 渲染
render() {
const { allowClear } = this.props;
const { selectedValue } = this.state;
return (
<div>
{/* 清除按钮,根据 allowClear 属性决定是否显示 */}
{allowClear && selectedValue !== null && (
<span onClick={this.handleClear}>Clear</span>
)}
{/* 下拉菜单等其他内容 */}
</div>
);
}
}
// 属性类型检查
Select.propTypes = {
allowClear: PropTypes.bool, // 是否显示清除按钮
value: PropTypes.any, // 选中的值
onChange: PropTypes.func, // 选中值变化时的回调函数
};
export default Select;
从上面代码我们可以得知,allowClear
的实现依赖于 selectedValue
的状态来确定是否显示清除按钮。当 value
属性被动态绑定时,可能会导致 selectedValue
和 value
的值不同步,从而影响了 allowClear
的表现。
具体来说,当 value
属性被动态绑定时,如果 value
的值发生了变化,但 selectedValue
没有相应地更新,那么 allowClear
可能会失效。这是因为 allowClear
的显示与隐藏是由 selectedValue
的状态决定的,如果 selectedValue
的值没有及时更新,那么清除按钮就不会正确地显示或隐藏。
解决方法--使用onMouseEnter鼠标移入事件
<Select
placeholder="请选择"
value={queryParam.eparchyName}
allowClear={true}
onMouseEnter={e => this.handleClear(e, 'eparchyCode')}
onSelect={(value, option) =>
this.setState({
queryParam: {
...queryParam,
eparchyCode: option.key,
eparchyName: value,
},
})
}
>
// 鼠标移入获取清空按钮
handleClear(e, str) {
const { queryParam } = this.state;
// 获取到dom元素
let clearDom = e.currentTarget;
// 添加点击事件
clearDom.addEventListener('click', () => {
// 清空操作
if (str == 'eparchyCode') {
this.setState({ queryParam: { ...queryParam, eparchyCode: '', eparchyName: '' } });
} else if (str == 'taskStatus') {
this.setState({ queryParam: { ...queryParam, taskStatus: '' } });
} else if (str == 'processStatus') {
this.setState({ queryParam: { ...queryParam, processStatus: '' } });
}
});
}
尽管allowClear的清除作用失效,但保留了清除图标。因此我们可以另辟蹊径,通过鼠标移入事件绑定点击事件,从而实现清除的操作。