React表单事件
在HTML中,表单元素与其他元素最大的不同是它自带值或数据,有表单元素就会有用户输入,就会有表单事件触发,就会涉及的数据处理。在React开发应用时,为了更好地管理应用中的数据,响应用户的输入,就会运用到受控组件与非受控组件这两个概念。
受控组件与非受控组件
受控组件:受控组件的值由props或state传入,用户在元素上交互或输入内容会引起应用state的改变。在state改变之后重新渲染组件,我们才能在页面中看到元素中值的变化。假如组件没有绑定事件处理函数改变state,用户的输入是不会起到任何效果的,这也就是受控的含义所在。表单状态发生变化时,都会通知React,将状态交给React进行处理,React通过事件处理函数(e.target.value)获取到表单的值。
非受控组件:类似于传统的DOM表单控件,用户输入不会直接引起应用state的变化,我们也不会直接为非受控组件传入值。想要获取非受控组件,我们需要使用一个特殊的ref属性,同样也可以使用defaultValue属性来为其指定一次性的默认值。非受控组件的值不受组件自身的state和props控制,非受控组件使用ref从DOM中获取元素数据
受控组件简单来说就是它的值由React进行管理,而非受控组件的值则由原生DOM进行管理。
//受控组件
<input type='text' value={this.state.value} onChange={this.handleChange}/>
handleChange(event) {
this.setState({value: event.target.value});
}
//非受控组件
<input type="text" defaultValue="hello!"/>
-
React中的组件分为受控组件和非受控组件
-
受控组件的两个要点:
- 组件的
value
属性与React
中的状态绑定 - 组件内声明了事件处理
value
的变化
- 组件的
-
非受控组件更像是传统的
HTML
表单元素,数据存储在DOM
中,而不是组件内部,获取数据的方式是通过ref
引用 -
使用总结:
- 尽可能使用受控组件
- 受控组件是将状态交由React处理,可以是任何元素,不局限于表单元素
- 对于有大量表单元素的页面,使用受控组件会使程序变得繁琐难控,此时使用非受控组件更为明智
- 在受控组件中,数据流是单向的(state是变化来源),因此在改变state时都应该使用setState,才会刷新页面
Refs
不能用于函数式组件,因为函数式组件没有实例- 在函数式组件内部,是可以使用
Refs
的,需要引入hook
常见的表单组件获取值
在组件中声明表单元素input,textarea,select等时,一般都要为表单元素传入应用状态中的值,我们需要根据表单元素中用户的输入,对应用数据进行相应的操作和改变。常见的表单包括输入框,单选框,复选框,下拉框和多文本框,在Vue中只需要使用v-model指令,但是在React中需要自己实现。
输入框
先给input框的value绑定一个值,然后通过input或者change改变事件来获取用户输入的值,并将这个值赋值给value绑定的值,再使用setState方法来重新渲染组件就可以实现数据的双向绑定了。最后表单收集的就是用户输入的value值。
<input type="text" value={this.state.phonen} onChange={this.phonenhandle}/>
this.phonenhandle=(e)=>{
console.log(e.target.value);
};
ps:没有使用setState函数页面不会刷新,渲染用户输入的数据。
<input type="text" value={this.state.phonen} onChange={this.phonenhandle}/>
this.phonenhandle=(e)=>{
console.log(e.target.value);
this.state.phonen=e.target.value;
this.setState(this.state);
};
单选框和复选框
radio和checkbox通过操作checked属性实现受控,value只起辅助作用。
单选框可以通过onChange事件获取value的值,所以可以通过value值间接控制是否选中,但是onChange只能获取value值,不能改变,将选中的value值赋值给表单要收集的数据变量就可以收集到选中的value值。
<label>
<input type="radio" name='sex' value='男' checked={this.state.sex=='男'} onChange={this.sexhandle}/>男
</label>
<label>
<input type="radio" name='sex' value='女' checked={this.state.sex=='女'} onChange={this.sexhandle}/>女
</label>
this.sexhandle = (e) => {
console.log(e.target.value);
this.state.sex = e.target.value;
this.setState(this.state);
};
复选框checked属性是对数组进行操作,通过一个state的数组来存储变更。也是通过value值间接控制是否选中,onChange同样只能获取value值,不能改变,在数组中收集选中的value值。
<label>
<input type="checkbox" value='篮球' checked={this.state.hobby.includes('篮球')} onChange={this.hobbyhandle} />篮球
</label>
<label>
<input type="checkbox" value='高尔夫' checked={this.state.hobby.includes('高尔夫')} onChange={this.hobbyhandle} />高尔夫
</label>
<label>
<input type="checkbox" value='乒乓球' checked={this.state.hobby.includes('乒乓球')} onChange={this.hobbyhandle} />乒乓球
</label>
<label>
<input type="checkbox" value='躺平摆烂' checked={this.state.hobby.includes('躺平摆烂')} onChange=</label>
this.hobbyhandle = (e) => {
console.log(e.target.value);
if(this.state.hobby.includes(e.target.value)){
// 已选中的再次点击取消选中,将value从数组中取消
this.state.hobby.splice(this.state.hobby.indexOf(e.target.value),1);
}else{
// 未被选中的添加到数组中
this.state.hobby.push(e.target.value)
}
console.log(this.state.hobby, 111);
this.setState(this.state);
}
select下拉框
关于select,可以通过循环渲染option;在之前的select中,value都是写在option上的,但是在React中,对select进行了简单的封装,需要将value放在select中就可以通过select的onChange事件获取当前选择的value。
<select value={this.state.city} onChange={this.cityhandle}>
{
cityarr.map((value,index)=>{
return <option key={index}>{value}</option>
})
}
</select>
this.cityhandle = (e) => {
this.state.city = e.target.value;
console.log(this.state.city, 111);
this.setState(this.state);
};
日期选择器
收集的是value值,就是选择的日期
<input type="date" value={this.state.date} onChange={this.datehandle} />
this.datehandle = (e) => {
this.state.date = e.target.value;
this.setState(this.state);
console.log(this.state.date, 111);
}
文件类型
<input type="file" onChange={this.filehandle}/>
this.filehandle=(e)=>{
console.log(e.target.files);
this.state.file=e.target.files[0];
this.setState(this.state);
}
文本框
文本框和输入框的text同理,收集的是value就是用户输入的内容。
<textarea value={this.state.text} onChange={this.texthandle}></textarea>
this.texthandle=(e)=>{
this.state.text=e.target.value;
this.setState(this.state);
console.log(this.state.text, 111);
}
import React, { Component } from 'react'
export default class Home extends Component {
constructor() {
super();
this.state = {
phonen: "",
sex: '',
city: '',
hobby: [],
date: '',
text:'',
file:''
};
this.phonenhandle = (e) => {
console.log(e.target.value);
this.state.phonen = e.target.value;
this.setState(this.state);
};
this.sexhandle = (e) => {
console.log(e.target.value);
this.state.sex = e.target.value;
this.setState(this.state);
};
this.cityhandle = (e) => {
this.state.city = e.target.value;
console.log(this.state.city, 111);
this.setState(this.state);
};
this.hobbyhandle = (e) => {
console.log(e.target.value);
if (this.state.hobby.includes(e.target.value)) {
// 已选中的再次点击取消选中,将value从数组中取消
this.state.hobby.splice(this.state.hobby.indexOf(e.target.value), 1);
} else {
// 未被选中的添加到数组中
this.state.hobby.push(e.target.value)
}
console.log(this.state.hobby, 111);
this.setState(this.state);
};
this.datehandle = (e) => {
this.state.date = e.target.value;
this.setState(this.state);
console.log(this.state.date, 111);
};
this.texthandle=(e)=>{
this.state.text=e.target.value;
this.setState(this.state);
console.log(this.state.text, 111);
};
this.filehandle=(e)=>{
console.log(e.target.files);
this.state.file=e.target.files[0];
this.setState(this.state);
}
}
render() {
let cityarr = ['请选择', '北京', '深圳', '杭州', '南京', '上海'];
return (
<div>
<input type="text" value={this.state.phonen} onChange={this.phonenhandle}/>
<br />
<label>
<input type="radio" name='sex' value='男' checked={this.state.sex=='男'} onChange={this.sexhandle}/>男
</label>
<label>
<input type="radio" name='sex' value='女' checked={this.state.sex=='女'} onChange={this.sexhandle}/>女
</label>
<br />
<label>
<input type="checkbox" value='篮球' checked={this.state.hobby.includes('篮球')} onChange={this.hobbyhandle} />篮球
</label>
<label>
<input type="checkbox" value='高尔夫' checked={this.state.hobby.includes('高尔夫')} onChange={this.hobbyhandle} />高尔夫
</label>
<label>
<input type="checkbox" value='乒乓球' checked={this.state.hobby.includes('乒乓球')} onChange={this.hobbyhandle} />乒乓球
</label>
<label>
<input type="checkbox" value='躺平摆烂' checked={this.state.hobby.includes('躺平摆烂')} onChange={this.hobbyhandle} />躺平摆烂
</label>
<br />
<select value={this.state.city} onChange={this.cityhandle}>
{
cityarr.map((value,index)=>{
return <option key={index}>{value}</option>
})
}
</select>
<br />
<input type="date" value={this.state.date} onChange={this.datehandle} />
<br />
<textarea value={this.state.text} onChange={this.texthandle}></textarea>
<br />
<input type="file" onChange={this.filehandle}/>
</div>
)
}
}