一、const color = this.props.color!; 二、this.props.onBlur ? this.props.onBlur(e): undefined;
以經過匿名類建立組件,並將其分配給常量,咱們將使用適當的道具類型將其轉換爲最終結果組件,同時保留實現中定義的全部「defaultProps」
react
globals.d.ts閉包
declare type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
在uitls中定義withDefaultPropsapp
export const withDefaultProps = <P extends object, DP extends Partial<P> = Partial<P>>( defaultProps: DP, Cmp: React.ComponentType<P> ) => { type RequiredProps = Omit<P, keyof DP> type Props = Partial<DP> & RequiredProps Cmp.defaultProps = defaultProps return (Cmp as React.ComponentType<any>) as React.ComponentType<Props> }
說明函數
==使用上面或者下面的實現均可以==
ui
input組件爲一個完整的例子:this
import classnames from 'classnames'; import * as React from 'react'; import { withDefaultProps } from '../utils'; import './style/input.styl'; const defaultProps = { type: 'text', value: '', disabled: false, readonly: false, maxlength: 60, placehololder: '', autofocus: false, autocomplete: '', clearable: false, passShow: false } type DefaultProps = Readonly<typeof defaultProps>; type InputInnerProps = { prepend?: React.ReactNode; append?: React.ReactNode; className?: string; style?: React.CSSProperties; onChange?: (value: string) => void; onBlur?: (e: React.FocusEvent<HTMLInputElement>) => void; onFocus?: (e: React.FocusEvent<HTMLInputElement>) => void; } & DefaultProps; const InputState = { isFocus: false, inputValue: '', open: false }; type State = Readonly<typeof InputState>; const Input = withDefaultProps( defaultProps, class extends React.Component<InputInnerProps, State> { readonly state: State = InputState; private inputRef: React.RefObject<any> = React.createRef(); getDerivedStateFromProps() { this.setState({ open: this.props.passShow, inputValue: this.props.value }) } private changeHander = (e: React.ChangeEvent<HTMLInputElement>):void => { this.setState({ inputValue: e.target.value }) this.props.onChange ? this.props.onChange(e.target.value) : undefined; } private handleFoucus = (e: React.FocusEvent<HTMLInputElement>):void => { this.props.onFocus ? this.props.onFocus(e): undefined; this.setState({ isFocus: true }) } private handleBlur = (e: React.FocusEvent<HTMLInputElement>):void => { this.props.onBlur ? this.props.onBlur(e): undefined; this.setState({ isFocus: true }) } private handleClear = ():void => { this.setState({ inputValue: '' }) this.inputRef.current.focus(); } private handlePwdEye = ():void => { this.setState({ open: !this.state.open }) } public render() { const { type, disabled, readonly, autocomplete, autofocus, clearable, passShow, className, style, prepend, append, ...restProps } = this.props; const { isFocus, inputValue, open } = this.state; const inputCls = classnames('afo-input', className, { 'afo-input--active': isFocus }) const inputType:string = type === 'password' && passShow ? 'text': type; const showClear:boolean = clearable && inputValue && !readonly && !disabled ? true: false; const showPwdEye:boolean = type === 'password' && passShow && !disabled ? true: false; return ( <div className={inputCls} style={style}> { prepend ? <div className="afo-input__prepend">{prepend}</div> : '' } <input className="afo-input__field" ref={this.inputRef} value={inputValue} {...restProps} type={inputType} disabled={disabled} readOnly={readonly} autoComplete={autocomplete} autoFocus={autofocus} onFocus={(e) => this.handleFoucus(e)} onBlur={(e) => this.handleBlur(e)} onChange={(e) => this.changeHander(e)} /> { append || showClear || showPwdEye? <div className="afo-input__append"> { showClear ? <div className="afo-input__clear" onClick={() => this.handleClear()}> <i className="afo-wrong" /> </div> : '' } { showPwdEye ? <div className="afo-input__eye" onClick={() => this.handlePwdEye()}> <i className={open ? 'afo-inupt__eye--visible' : 'afo-inupt__eye--invisible'} /> </div> : '' } {append} </div> :'' } </div> ) } } ) export default Input;
條件類型映射的簡陋工廠/閉包標識函數模式。rest
注意,咱們使用了與withDefaultProps函數相似的類型映射構造,但咱們不將defaultProps映射爲可選的,由於它們在組件實現中是不可選的。code