Antd源碼淺析(二)InputNumber組件 一

前言

上篇咱們講了Icon組件,Icon組件是Antd源碼庫中實現比較簡單的組件,適合你們入門,這篇文章主要和你們一塊兒分析一下數字輸入框組件,即InputNumber,難度適中,但蘊含的Antd裏較爲經典的開發場景,適合你們比較深刻的瞭解Antd背後的思想。react

這篇咱們學習的目的主要有:git

  • 學習Antd的如何基於現有的組件封裝
  • 封裝背後的技術目的和效果如何

目錄結構

首先咱們依舊看看位於components 文件夾下的input-number 目錄結構:github

![alt text](/images/antd/2_1.png)

InputNumber組件的的效果圖以下:antd

![alt text](/images/antd/2_2.png)

代碼

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可能部分讀者比較陌生,咱們來介紹一下。this

Antd的許多組件都是基於rc-xxx組件分裝,好比常見的Table組件是基於rc-table,Form組件基於rc-form,rc-xxx來源於react-component組件庫,裏面有不少經常使用的組件,你們也能夠在項目中直接使用,也能夠通過本身二次封裝後使用。咱們稍後仔細分析一下rc-input-number,先來看看參數校驗和主體結構。spa

參數校驗

對於參數校驗,固然須要對照InputNumber的文檔看了,官方的使用說明以下:code

屬性以下:component

成員 說明 類型 默認值
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提供的舊版的this.refs.inputNumberRef字符串形式,但在最新版React16.2的文檔中,官方建議使用React.createRef(),這裏用普通的寫法能夠寫爲:

constructor(props) {
    super(props);
    this.inputNumberRef = React.createRef();
  }
  ...
  render() {
    ...
    return <RcInputNumber ref={this.inputNumberRef} className={inputNumberClass} {...others} />;
  }

  focus() {
    this.inputNumberRef.focus();
  }

  blur() {
    this.inputNumberRef.blur();
  }
}

到這裏,對於InputNumber組件的源碼主體結構介紹完了,咱們下一篇文章,分析一下核心的rc-input-number源碼,即<RcInputNumber/>組件的實現。

相關文章
相關標籤/搜索