import React, { CSSProperties, Component, ChangeEvent, createRef } from 'react' import classNames from 'classnames' import _ from 'lodash' interface SwitchProps { type?: string checked?: boolean disabled?: boolean on?: string off?: string onChange?(checked: boolean): void className?: string style?: CSSProperties } interface SwitchState { checked: boolean labelWidth: number | null isReady: boolean } class Switch extends Component { static displayName = 'Switch' static defaultProps = { type: 'default', on: '', off: '', onChange: _.noop, } readonly state: SwitchState = { checked: this.props.checked, labelWidth: null, isReady: false, } private _inputOffRef = createRef() private _inputOnRef = createRef() componentDidMount() { // 初始化后开始计算on和off的宽度,取较大值作为switch开关的宽度 const labelWidth = this._inputOffRef.current!.offsetWidth >= this._inputOnRef.current!.offsetWidth ? this._inputOffRef.current!.offsetWidth + 7 : this._inputOnRef.current!.offsetWidth + 7 this.setState({ labelWidth: Math.max(labelWidth, 34), isReady: true, }) } // eslint-disable-next-line camelcase UNSAFE_componentWillReceiveProps(nextProps: Readonly) { if ('checked' in nextProps) { this.setState({ checked: nextProps.checked, }) } } setChecked(checked: boolean): void { if (!('checked' in this.props)) { this.setState({ checked, }) } const { onChange } = this.props onChange && onChange(checked) } private _handleChange = (event: ChangeEvent): void => { if (this.props.disabled) { return } this.setChecked(event.target.checked) } render() { const { className, // checked, onChange, // eslint-disable-line type, disabled, on, off, ...rest } = this.props let style: CSSProperties = { width: this.state.labelWidth as number, } if ('style' in rest) { style = Object.assign({}, style, rest.style) } return ( <> {!this.state.isReady && ( )} ) } } export default Switch export type { SwitchProps }