自制ant.design表格组件教程

前言

在实际项目中我们时常有可能需要Ip地址输入框,键值对输入框这样的复杂输入组件。但是ant design
官方并没有给出这样的组件,文档中也没有提到应该如何写出这样的组件。

我在研究了一番实现了该功能,在这里与大家分享一下,希望可以方便到后来人。

源码分享

对于不需要教程的同学可以直接查看源码:

教程-编写一个IP输入组件

第一步:完全受控组件与ant design表格组件联动

首先我们需要建立一个完全受控的输入组件,并且该组件可以嵌套进ant design的表格组件当中并正常
运行。

{getFieldDecorator('ip')(
  <IpInput />
)}

IpInput组件代码:

import React, {Component} from 'react';
import {Input} from "antd";

export default class IpInput extends Component {
  constructor(props) {
    super(props);

    this.state = {
      ip: '',
    }
  }


  hdlInputChange = (e) => {
    this.setState({ip: e.target.value})
    this.props.onChange({target: {value: e.target.value}})
  }

  render() {
    return (
      <div>
        <Input value={this.state.ip} onChange={this.hdlInputChange} />
      </div>
    );
  }
}

在CodeSandbox中浏览

第二步:在IpInput组件中建立多个Input,并联动

重点是输出值的拆分与聚合

hdlInputChange = (e, block) => {
    let ipAdressArr = [this.state.ablock, this.state.bblock, this.state.cblock, this.state.dblock]
    let value = e.target.value
    this.setState({[`${block}block`]: value})
    ipAdressArr[blockDict[block]] = value
    this.props.onChange({target: {value: ipAdressArr.join('.')}})
  }

详细代码请看:CodeSandbox

到这一步一个基本的ip Input输入组件已经成型,但是难点部分还未开始。

第三步:校验规则处理

如果现在我们就开始正常使用该组件,4个输入框的报错样式必定是同时出现的。一个是红框的话,其他
三个也必定是红框状态。这是ant design的程序设计,FormItem的报错样式由外层容器通过CSS控制。

上面这段话不容易理解的话自己试一下就明白了。

也就是说我们需要单独控制4个Input框的校验状态,已经有数字的应为正确状态,没有数字的校验时显示为
红色。且这个校验行为要能够被ant designForm组件触发。

首先我们建立一个类似ant design原生的Form.Item组件用来包裹每个Input并负责校验逻辑。

class FromItemValidatorWarpper extends Component {
  constructor(props) {
    super(props)

    this.state = {
      validateStatus: ''
    }
  }

  componentDidMount () {}

  componentDidUpdate (prevProps, prevState) {
    if(this.props.valiating && prevProps.validating !== this.props.valiating){
      // form 触发的 validating

      let validateStatus = ''
      if(!this.getChildProp("value")){
        validateStatus = 'error'
      }
      if(this.state.validateStatus !== validateStatus){
        this.setState({validateStatus})
      }

    }
  }

  getChildProp(prop) {
    const child = this.props.children
    return child && child.props && child.props[prop];
  }

  render() {
    return (
      <Form.Item
        validateStatus={this.state.validateStatus}
      >
        {this.props.children}
      </Form.Item>
    )
  }
}

然后用该组件包裹IpInput组件

<FromItemValidatorWarpper valiating={this.state.valiating}>
  <Input value={this.state.dblock} onChange={(e)=>{this.hdlInputChange(e, 'd')}} />
</FromItemValidatorWarpper>

IpInput组件中建立valiating属性,并使其和外层ant design Form组件的validator联动。

  componentDidUpdate(prevProps) {
    let dataField = this.props["data-__field"]

    if(dataField.errors && !prevProps["data-__field"].errors){
      // valitor 函数触发报错
      this.setState({valiating: true})
    }
    if(!dataField.errors && prevProps["data-__field"].errors){
      // valitor 函数触发清除报错
      this.setState({valiating: false})
    }
  }

最后在使用IpInput的组件位置添加一个正则校验。

  {getFieldDecorator('ip', {
    rules: [
      {required: true, message: 'Please input your ip!'},
      {
        pattern: /((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))/,
        message: 'Please finish your ip!'
      }
    ],
  })(
    <IpInput/>
  )}

请在CodeSandbox中查看效果

OK,我们现在只差最后一步了,即在外层使用组件时使用setFieldsValue初始化组件值的功能。

第四步:setFieldsValue方法支持

componentDidUpdate方法中加入一段代码判断组件上级value是否和内部value相同,不同且没有进行
初始化时进行初始化。

if(dataField.value !== [this.state.ablock, this.state.bblock, this.state.cblock, this.state.dblock].join('.') && !this.initialized){
  this.initialized = true
  let ipAdressArr = dataField.value.split('.')
  this.setState({
    ablock: ipAdressArr[0],
    bblock: ipAdressArr[1],
    cblock: ipAdressArr[2],
    dblock: ipAdressArr[3],
  })
}

请在CodeSandbox中查看效果

结尾

以上,一个IP输入组件基本完成了。细节包括样式还有很多可以优化的地方,我在这里就不继续了。maybe
以后再来更新。

我把最后的完整代码放在github上,有任何建议可
以给我提交issue或下面评论回复,谢谢。


 上一篇
原生面经从初级到高级 原生面经从初级到高级
原文链接 函数1.1函数的3种定义方法1.1.1 函数声明//ES5 function getSum(){} function (){}//匿名函数 //ES6 ()=>{}//如果{}内容只有一行{}和return关键字可省, 1
2019-10-25
下一篇 
联通G2-40盒子刷机教程 联通G2-40盒子刷机教程
第一步 下载刷机包链接: 百度云 提取码: um8d 第二步 准备刷机U盘 U盘格式化为FAT32格式 解压下载的刷机包,将解压内容复制到U盘根目录 第三部 拆机 卸下底部的4颗螺丝,卸下顶部面板 短接J38跳线 我使用的是一根回形针
2019-09-27
  目录