Antd源码浅析(⼆)InputNumber组件⼀
前⾔
上篇我们讲了Icon组件,Icon组件是Antd源码库中实现⽐较简单的组件,适合⼤家⼊门,这篇⽂章主要和⼤家⼀起分析⼀下数字输⼊框组件,即InputNumber,难度适中,但蕴含的Antd⾥较为经典的开发场景,适合⼤家⽐较深⼊的了解Antd背后的思想。
这篇我们学习的⽬的主要有:
学习Antd的如何基于现有的组件封装
封装背后的技术⽬的和效果如何
⽬录结构
⾸先我们依旧看看位于components ⽂件夹下的input-number ⽬录结构:
InputNumber组件的的效果图如下:
代码
InputNumber的核⼼代码位于 index.tsx 内,代码不多,我们直接贴过来:
import * as React from 'react';
import classNames from 'classnames';
import RcInputNumber from 'rc-input-number';
export interface InputNumberProps {
prefixCls?: string;
min?: number;
max?: number;
value?: number;
step?: number | string;
defaultValue?: number;
tabIndex?: number;
onKeyDown?: React.FormEventHandler<any>;
onChange?: (value: number | string | undefined) => void;
disabled?: boolean;
size?: 'large' | 'small' | 'default';
formatter?: (value: number | string | undefined) => string;
parser?: (displayValue: string | undefined) => number;
placeholder?: string;
style?: React.CSSProperties;
className?: string;
name?: string;
id?: string;
precision?: number;
}
export default class InputNumber extends React.Component<InputNumberProps, any> {
static defaultProps = {
prefixCls: 'ant-input-number',
step: 1,
};
private inputNumberRef: any;
render() {
const { className, size, ...others } = this.props;
const inputNumberClass = classNames({
[`${this.props.prefixCls}-lg`]: size === 'large',
[`${this.props.prefixCls}-sm`]: size === 'small',
}, className);
return <RcInputNumber ref={(c: any) => this.inputNumberRef = c} className={inputNumberClass} {...others} />;
}
focus() {
this.inputNumberRef.focus();
}
blur() {
this.inputNumberRef.blur();
}
}
主要结构⾮常清晰,分成三个部分,头部的⽂件引⼊,参数校验,主体类声明。
⽂件的引⼊中,react⼤家⾮常熟悉,classnames 在上篇⽂章,河马君为⼤家介绍过使⽤⽅法和实现,对于rc-input-number可能部分读者⽐较陌⽣,我们来介绍⼀下。
Antd的许多组件都是基于rc-xxx组件分装,⽐如常见的Table组件是基于rc-table,Form组件基于rc-form,rc-xxx来源于组件库,⾥⾯有很多常⽤的组件,⼤家也可以在项⽬中直接使⽤,也可以经过⾃⼰⼆次封装后使⽤。我们稍后仔细分析⼀下rc-input-number,先来看看参数校验和主体结构。
参数校验
对于参数校验,当然需要对照InputNumber的⽂档看了,官⽅的使⽤说明如下:
属性如下:
成员说明类型默认值
autoFocus⾃动获取焦点boolean false
defaultValue初始值number
disabled禁⽤boolean false
formatter指定输⼊框展⽰值的格式function(value: number \string): string
max最⼤值number Infinity
min最⼩值number-Infinity
parser指定从 formatter ⾥转换回数字的⽅式,和 formatter 搭配使⽤function( string): number-
precision数值精度number-
size输⼊框⼤⼩string⽆
step每次改变步数,可以为⼩数number\string
value当前值number
onChange变化回调Function(value: number \string)
那我们再来对照代码⾥的参数校验,⽂档中有的就不再赘述,缺少的通过注释给出:
export interface InputNumberProps {
prefixCls?: string;  // Antd预留给⾃⼰的预设class,这⾥在defaultProps中默认设置为'ant-input-number'
min?: number;
max?: number;
value?: number;
step?: number | string;
defaultValue?: number;
tabIndex?: number;    //tab 键控制次序,就是快捷切换
onKeyDown?: React.FormEventHandler<any>;  // ⽤户按下键盘按键时的回调函数
onChange?: (value: number | string | undefined) => void;
disabled?: boolean;
size?: 'large' | 'small' | 'default';
formatter?: (value: number | string | undefined) => string;
parser?: (displayValue: string | undefined) => number;
placeholder?: string;    // placeholder提⽰
style?: React.CSSProperties;  // ⽤户⾃定义style
className?: string;  // ⽤户⾃定义class
name?: string;    // ⽤户⾃定义name属性,毕竟底层是input标签
id?: string;  // ⽤户⾃定义id
precision?: number;
}
对于其中TypeScript形式类型校验,可以参考上篇⽂章,这⾥Antd⽂档给出了其⾃定义的参数列表,省略了默认的普通参数,所以通过对于源码的学习,能够清晰的知道在官⽅⽂档之外,哪些参数是可⽤的。
主体函数
export default class InputNumber extends React.Component<InputNumberProps, any> {
// 默认参数设置
static defaultProps = {
prefixCls: 'ant-input-number',
step: 1,
};
// 通过ref属性获取实例
private inputNumberRef: any;
render() {
const { className, size, ...others } = this.props;
// className的判断和合成
const inputNumberClass = classNames({
[`${this.props.prefixCls}-lg`]: size === 'large',
[`${this.props.prefixCls}-sm`]: size === 'small',
}, className);
/
/ 核⼼RcInputNumber组件,我们稍后讲解⼀下
return <RcInputNumber ref={(c: any) => this.inputNumberRef = c} className={inputNumberClass} {...others} />;
}
// 通过实例绑定的focus事件和blur事件
focus() {
this.inputNumberRef.focus();
}
blur() {
this.inputNumberRef.blur();
}
}
这是官⽅给出的⽅法⽂档:
名称描述
blur()移除焦点
focus()获取焦点
这⾥河马君多说⼀下,对于这两个函数的实现,Antd使⽤了ref属性,实现对组件的引⽤
ref={(c: any) => this.inputNumberRef = c}
这是通过ref回调的⽅式,在组件render完获取实例,优于React提供的旧版的fs.inputNumberRef字符串形式,但在最新版React16.2的⽂档中,官⽅建议使⽤ateRef(),这⾥⽤普通的写法可以写为:
constructor(props) {
super(props);
this.inputNumberRef = ateRef();
input标签placeholder属性
}
...
render() {
...
return <RcInputNumber ref={this.inputNumberRef} className={inputNumberClass} {...others} />;
}
focus() {
this.inputNumberRef.focus();
}
blur() {
this.inputNumberRef.blur();
}
}
到这⾥,对于InputNumber组件的源码主体结构介绍完了,我们下⼀篇⽂章,分析⼀下核⼼的rc-input-number源码,即<RcInputNumber/>组件的实现。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。