React躬行记——表单
Posted strick
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React躬行记——表单相关的知识,希望对你有一定的参考价值。
表单元素是一类拥有内部状态的元素,这些状态由其自身维护,通过这类元素可让用户与Web应用进行交互。html中的表单元素(例如<input>、<select>和<radio>等)在React中都有相应的组件实现,不仅如此,React还将它们分成两种:受控组件和非受控组件。
一、受控组件
受控组件(Controlled Component)是指那些受React控制的表单元素,其状态(value、checked等属性)的变更由组件的state管理。对于不同的表单元素,其受控组件的形式会有所差异,接下来会讲解其中的三类。
1)文本框
常用的单行文本框是一个type属性为“text”的<input>元素,它的值(即状态)由value属性控制。如果要监听文本框的状态变化,那么可以像下面这样操作。
class Text extends React.Component constructor(props) super(props); this.state = value: "init"; this.handle = this.handle.bind(this); handle(e) this.setState(value: e.target.value.toUpperCase()); render() return <input value=this.state.value onChange=this.handle type="text" />;
上述代码实现了一个简单的功能,在改变文本框中的内容时,自动将其转换成大写字母。具体的更新过程可分为四步:
(1)在构造函数中初始化组件的state,并为文本框设置默认值。
(2)文本框注册onChange事件,监听其值的变化。
(3)在事件处理程序handle()中,通过e.target.value读取到输入的值,修改并同步(调用this.setState()方法)到组件的state中。
(4)组件重新渲染,完成文本框的内容更新。
其他两类受控组件的更新过程与之类似,只是在细节处理上有所不同。
观察上面的示例可以发现,文本框的数据来源于组件的state,通过onChange事件将输入的新数据再同步给组件的state,从而完成了一次双向数据绑定。
React中的<textarea>元素(多行文本框),其使用类似于上面的<input>元素,也是通过value属性来获取值的,如下代码所示,省略了构造函数和事件处理程序。
class TextArea extends React.Component render() return <textarea value=this.state.value onChange=this.handle />;
而HTML中的<textarea>元素则会将值定义成子元素,并且包含结束标签,如下所示。
<textarea>init</textarea>
2)单选框和复选框
单选框是一个type属性为“radio”的<input>元素,复选框是一个type属性为“checkbox”的<input>元素。与之前的文本框不同,React控制的不是它们的值,而是选中状态,即布尔属性checked。在下面的例子中,监听了每个单选框的checked属性。
class Radio extends React.Component constructor(props) super(props); this.state = gender: "" ; this.handle = this.handle.bind(this); handle(e) this.setState( gender: e.target.value ); render() return ( <> <input name="gender" value="1" onChange=this.handle type="radio" checked=this.state.gender == "1" />男 <input name="gender" value="2" onChange=this.handle type="radio" checked=this.state.gender == "2" />女 </> );
复选框能选中多个项,其操作要比单选框繁琐许多。在下面的例子中,不但监听了每个复选框的checked属性,还将处于选中状态的值提取了出来,组成一个数组。
class Checkbox extends React.Component constructor(props) super(props); this.state = colors: [] ; //保存复选框值的数组 this.handle = this.handle.bind(this); handle(e) const checked, value = e.target; let colors = this.state; if (checked && colors.indexOf(value) == -1) colors.push(value); //已选中并且数组中未有该值,就在末尾插入 else colors = colors.filter(item => item != value); //未选中,就将该值过滤掉 this.setState( colors ); render() return ( <> <input name="colors" value="1" onChange=this.handle type="checkbox" checked=this.state.colors.indexOf("1") >= 0 />红 <input name="colors" value="2" onChange=this.handle type="checkbox" checked=this.state.colors.indexOf("2") >= 0 />绿 <input name="colors" value="3" onChange=this.handle type="checkbox" checked=this.state.colors.indexOf("3") >= 0 />蓝 </> );
虽然React处理单选框和复选框的方式要比在HTML中复杂一点,但是保证了组件的state是元素状态的唯一来源,进而让更新过程更加可靠和可控。
3)选择框
在HTML中,<select>元素(选择框)会包含多个用来表示选项的<option>元素,而选中的项会被定义一个selected属性,如下代码所示,第二个<option>元素处于选中状态。
<select> <option value="1">strick</option> <option value="2" selected>freedom</option> <option value="3">jane</option> </select>
在React中,只需对<select>元素定义value属性就能决定当前的选中项,如下代码所示,这比用DOM的方式操作选项要简洁得多。
class Select extends React.Component constructor(props) super(props); this.state = value: "" ; this.handle = this.handle.bind(this); handle(e) this.setState( value: e.target.value ); render() return ( <select value=this.state.value onChange=this.handle> <option value="1">strick</option> <option value="2">freedom</option> <option value="3">jane</option> </select> );
只要给<select>元素添加multiple属性并将其赋为true就能变为多选,如下代码所示,此时传给value属性的是一个数组。
class MulSelect extends React.Component constructor(props) super(props); this.state = values: [] ; this.handle = this.handle.bind(this); handle(e) const options = e.target; //options是一个类数组对象 const values = Object.keys(options) //将options的索引组成一个数组 .filter(i => options[i].selected) //过滤出选中项 .map(i => options[i].value); //提取选中项组成新数组 this.setState( values ); render() return ( <select value=this.state.values onChange=this.handle multiple=true> <option value="1">strick</option> <option value="2">freedom</option> <option value="3">jane</option> </select> );
二、非受控组件
非受控组件(Uncontrolled Component)的定义正好与受控组件的相左,其状态由自己管理,通常使用ref属性(第5篇中讲解过)获取表单元素的值。在下面的示例中,文本框在失去焦点时,能自动将其内容转换成大写字母。如果用受控组件的形式完成相同的功能,那么会较为繁琐。
class Text extends React.Component constructor(props) super(props); this.handle = this.handle.bind(this); handle() this.input.value = this.input.value.toUpperCase(); render() return <input onBlur=this.handle type="text" ref= input => this.input = input/>;
在render()方法中,首先为文本框注册onBlur事件,然后定义ref属性,其值是一个回调函数。当组件被挂载时,就会执行该回调函数,然后就能让this.input指向一个文本框,从而在事件处理程序handle()中就能通过this.input读取到文本框中的内容。
在React中,有一个表单元素比较特殊,那就是上传按钮。它只有非受控组件的形式,因为其值只能由用户传入,不能被组件的state所控制。
1)默认值
如果要指定非受控组件的默认值,那么可通过定义defaultValue或defaultChecked属性实现,前者适用于文本框、选择框等元素,后者适用于单选框和复选框。下面的示例分别给文本框和单选框设置了默认值,为了便于观察,只放出了关键代码。
class Text extends React.Component render() return <input type="text" defaultValue="init"/>; class Radio extends React.Component render() return ( <> <input name="gender" value="1" type="radio"/>男 <input name="gender" value="2" type="radio" defaultChecked=true/>女 </> );
以上是关于React躬行记——表单的主要内容,如果未能解决你的问题,请参考以下文章