💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 一、表单(Forms) > HTML 表单元素与 React 中的其他 DOM 元素有所不同,因为表单元素自然地保留了一些内部状态。例如,这个纯 HTML 表单接受一个单独的 name ### 1.1 受控组件 > 在 HTML 中,表单元素如 \<input\>,\<textarea\> 和 \<select\> 表单元素通常保持自己的状态,并根据用户输入进行更新。而在 React 中,可变状态一般保存在组件的 state(状态) 属性中,并且只能通过 setState() 更新。 ``` <input type="text" value={this.state.value} onChange={(e) => { this.setState({ value: e.target.value.toUpperCase(), }); }} /> ``` > 如上:在React中 的表单元素input,绑定了change事件,其value值与组件state属性相关联,每当表单的状态发生变化,都会被写入组件的state中,这种组件叫 **受控组件** > 从形式上看,受控组件即绑定有**value值**的组件(且需要有onChange事件响应函数对应当value值变化时的处理),非受控组件就是没有绑定value值的组件 ``` class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A name was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } ``` - 受控组件两要素:value,onChange ### 1.2 textarea标签 > 在 React 中,\<textarea\> 的赋值使用 **value 属性**替代。这样一来,表单中 \<textarea\> 的书写方式接近于单行文本输入框 ``` class EssayForm extends React.Component { constructor(props) { super(props); this.state = { value: 'Please write an essay about your favorite DOM element.' }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('An essay was submitted: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name: <textarea value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> ); } } ``` - 注意,this.state.value 在构造函数中初始化,所以这些文本一开始就出现在文本域中。 ### 1.3 select标签 - select标签的值由 **value**指定,而不是使用selected属性 - onChange事件绑定 当select对应的state变化时的操作函数 ``` class FlavorForm extends React.Component { constructor(props) { super(props); this.state = {value: 'coconut'}; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('Your favorite flavor is: ' + this.state.value); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Pick your favorite La Croix flavor: <select value={this.state.value} onChange={this.handleChange}> <option value="grapefruit">Grapefruit</option> <option value="lime">Lime</option> <option value="coconut">Coconut</option> <option value="mango">Mango</option> </select> </label> <input type="submit" value="Submit" /> </form> ); } } ``` - 您可以将一个数组传递给 value 属性,允许你在 select 标签中选择多个选项: ``` selectChange(e) { let val = e.target.value; this.setState(prev=>{ const prevLike = prev.like; console.log(val) if (prevLike.indexOf(val) == -1) { prevLike.push(val) } else { prevLike.forEach((item,index) => { if (item == val) { prevLike.splice(index,1) return; } }) } return { like: prevLike } }) } render() { return ( <form onSubmit={this.handleSubmit.bind(this)}> <div>name: <input type="text" value={this.state.name} onChange={(e) => this.setState({ name: e.target.value })} /></div> <div>like: <select multiple='multiple' value={this.state.like} onChange={this.selectChange.bind(this)}> <option value="orange">orange</option> <option value="pear">pear</option> <option value="Apple">Apple</option> <option value="melon">melon</option> </select> </div> <input type='submit' value='submit'/> <div> show:{this.state.name} like {this.state.like} </div> </form> ) } ``` ### 1.4 表单多元素处理 >当需要处理多个受控的input元素时,可以为元素添加name属性,并让处理函数根据event.target.name的值来选择要做什么 ``` handleChange(e) { var target = e.target, name = target.name, val = target.type==='checkbox'||target.type==='radio'?target.checked:target.value; this.setState({ [name]:val }) } render() { return ( <form onSubmit={this.handleSubmit.bind(this)}> <div>name: <input name="name" type="text" value={this.state.name} onChange={this.handleChange.bind(this)} /></div> <div>password:<input name="pwd" type='password' value={this.state.pwd} onChange={this.handleChange.bind(this)}/></div> <input type='submit' value='submit'/> <div> show:{this.state.name} like {this.state.like} </div> </form> ) } ``` - 注意:此处用到了ES6的[计算属性名](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Object_initializer)\[name\]来表示对应的state值 ### 受控组件缺点 - 有时使用受控组件有些乏味,因为你需要*为每一个可更改的数据提供事件处理器*,并*通过 React 组件管理所有输入状态*。 - 在受控组件中,表单数据由React组件负责处理。而在非受控组件中,表单数据由DOM元素本身处理。 - 性能问题:在受控组件中,每次表单的值发生变化都会调用onChange事件处理器,这确实会带来性能上的损耗(这个问题可以通过Flux/Redux应用架构等方式来达到统一组件状态的目的) ## 二、非受控组件 > 在表单组件中,没有value属性(单复先没有checked属性)时,可以称之为非受控组件。 - 使用defaultValue和defaultChecked来表示组件的默认状态; - 通过 defaultValue和defaultChecked来设置组件的默认值,它仅会被渲染一次,在后续的渲染时并不起作用 ``` handleSubmit(e) { e.preventDefault(); const nameInput = this.nameInput.value, pwdInput = this.pwdInput.value; console.log(nameInput,pwdInput) } render() { return ( <form onSubmit={this.handleSubmit.bind(this)}> <div>name: <input name="name" type="text" defaultValue="admin" ref={i=>this.nameInput=i}/></div> <div>password:<input name="pwd" type='password' ref={i=>this.pwdInput=i}/></div> <input type='submit' value='submit'/> </form> ) } ``` - defaultValue或defaultChecked来设置默认值 - ref为一个接受DOM元素作为参数的回调函数,在其中可以将DOM元素映射到组件中再取值