表单大家都很清楚,input 框,select, radio 等, 在 vue 中的表单数绑定使用的是 v-model, v-model 是啥,一个语法糖,用于双向数据绑定而已,在react 中是没有这样的语法糖的,需要自己来手动实现
受控组件和非受控组件
受控组件:组件的使用者,有能力完全控制该组件的行为和内容。通常情况下,受控组件往往没有自身的状态,其内容完全收到属性的控制。
非受控组件:组件的使用者,没有能力控制该组件的行为和内容,组件的行为和内容完全自行控制。
在react 表单组件中,默认情况下是非受控组件,一旦设置了表单组件的value属性,则其变为受控组件(单选和多选框需要设置checked)
input
效果: 和 vue 一样,双向数据绑定,但是这个并没有特殊的语法糖
封装的代码如下:
Input.tsx
import React from 'react' /** * input 的属性 */ interface IInputP { /** * 属性值 */ value: any, /** * 表单的属性名字 */ name: string, /** * 输入框改变的函数 */ onChange: (value: any, name: string, e: React.ChangeEvent<HTMLInputElement>) => void; } export default function Input(props: IInputP) { return ( <> <input type="text" value={props.value} name={props.name} onChange={e => props.onChange(e.target.value, props.name, e)} /> </> ) }
使用方式
import React, { Component } from 'react' import Input from '.' interface IInputTestS { /** * 属性值 */ value: any, } export default class InputTest extends Component<{}, IInputTestS> { state:IInputTestS = { value: 1 } change = (v: any) => { this.setState(pre => ({ value: v })) } render() { return ( <div> <Input value={this.state.value} name='test' onChange={this.change}></Input> </div> ) } }
这个数据绑定和 vue 的原理是一样的,都是通过 元素的 value 值 和 change 事件来进行双向数据绑定的,只是vue 中提供了特殊的语法糖 v-model
radio, select
实现方法和上面的input 是一样的
checkbox
这个的实现方式有点不一样,多选传入的肯定是一个数组
封装的代码如下:
CheckboxGroup .tsx
import React, { Component } from 'react' /** * 每一个radio的对象类型 */ type checkboxObj = { value: string , label: string | number } interface ICheckboxGroupP { /** * 选中的值 */ choose: string[] , /** * 标签的name 值 */ name: string, /** * 数据集合 */ data: checkboxObj[] /** * change 事件 */ onChange: (v: any, name: string, e: React.ChangeEvent<HTMLInputElement>) => void, } export default class CheckboxGroup extends Component<ICheckboxGroupP> { /** * 获取checkbox */ getCheckbox = ():JSX.Element[] => { return this.props.data.map(p => { return ( <label key={p.value}> <input type='checkbox' name={this.props.name} checked={this.props.choose.includes(p.value)} value={p.value} onChange={e => this.props.onChange(e.target.value,this.props.name,e )} /> {p.label} </label> ) }) } render() { return ( <div> {this.getCheckbox()} </div> ) } }
使用方式
import React, { Component } from 'react' import CheckboxGroup from '.' /** * 按钮组 */ interface ICheckboxGroupTestS { choose: string[], data: checkboxObj[] } /** * 每一个radio的对象类型 */ type checkboxObj = { value: string, label: string | number } export default class CheckboxGroupTest extends Component<{}, ICheckboxGroupTestS> { state: ICheckboxGroupTestS = { choose: ['football'], data: [ { value: 'football', label: '足球' }, { value: 'basketball', label: '篮球' }, { value: 'tennis', label: '网球' }, ] } render() { return ( <> <CheckboxGroup name='test' data={this.state.data} choose={this.state.choose} onChange={(v: string, name: string, e: React.ChangeEvent<HTMLInputElement>)=>{ let arr = [...this.state.choose]; if(e.target.checked){ arr.push(v); }else{ arr = arr.filter(f => f !== v); } this.setState(pre => ({ choose: arr })) }}/> </> ) } }
源码地址:
https://github.com/cll123456/react-learn/tree/master/src/pro/form
最终效果