一、绑定事件
1、绑定事件处理函数this获取数据的几种方法:
第一种方式:在事件上使用bind(this)
<button onClick={this.getData1.bind(this)}>获取数据方法1</button>
第二种方式:在构造函数中改变this指向
this.getData2=this.getData2.bind(this)
<button onClick={this.getData2}>获取数据方法2</button>
第三种方式:使用=()=>
getData3=()=>{
alert(this.state.dataMsg)
}
<button onClick={this.getData3}>获取数据方法3</button>
关于React中this指向问题
JavaScript函数中的this不是在函数声明的时候定义的,而是在函数调用(即运行)的时候定义的。在react中也遵循这个原则,this指向该function的调用方,所以“调用者”不同会导致this的不同,这里的“调用者”指的是函数执行时的当前对象。
箭头函数或是bind会改变this的指向。上面的this.state,之所以能够访问到state就是改变了this的指向,不然getData里的this就是指向这个function,这是的this是undefined。
一般来说:
1、谁调用的this就指向谁。
2、箭头函数,bind改变后的指向父层。
2、对state中的数据进行赋值
在react中我们使用setState来更新数据:
dataMsg:'原数据'
setData=()=>{
//此处使用setState来更新数据
this.setState({
dataMsg:'数据已被改变'
})
console.log(this.state.dataMsg)
}
但是console打印出来的值是:原数据。
这里就要提到react里setState的异步了,在react里setState这个方法是异步的,不会按顺序执行,它可能会等待一组state一起进行更新,来提高性能。下面提供一个解决办法,setState的回调setState(updater[, callback]),相当于componentDidUpdate函数:
setData=()=>{
//此处使用setState来更新数据
//setState的回调setState(update, ()=>{//更新完后执行的代码}),
this.setState({
dataMsg:'数据已被改变'
},()=>{
console.log(this.state.dataMsg)
}
}
3、方法的传值
因为在事件中使用onClick={this.setData()}时方法直接执行,直接写成this.setData(data)这样会报错,所以需要使用bind():
//看参数,第一个参数需要是this或是一个函数
//第二个参数为需要传递参数
bind(this: Function, thisArg: any, ...argArray: any[]): any)
下面看如何传递:
<button className="myFormEvent-setData2-btn" onClick={this.setData.bind(this,["第一个参数","第二个参数","第三个参数"])}>执行方法传值2</button>
//多个参数时str即为数组
setData=(str)=>{
this.state({
msg:str[0],
dataMsg:str[2]
})
}
二、事件对象
事件对象:在出发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。
1、使用event.target获取相关属性值:
event.target.style.background //获取或更改背景色
event.target.getAttribute("aid") //获取自定义属性的值
event.target.setAttribute("aid","aaa")//设置自定义属性的值
e.target.value //获取输入框的值
//按钮点击事件
<button aid="aaa" onClick={this.getEvent}></button>
getEvent=(event)=>{
//使用event.target来改变颜色
event.target.style.background="red";
//使用event.target.getAttribute("aid")里获取button的自定义属性aid的值
//使用event.target.setAttribute("aid","aaa")来设置button的自定义属性aid的值
console.log(event.target.getAttribute("aid"));
}
//输入框改变事件
<input onChange={this.inputChange}></input>
inputChange=(e)=>{
//使用event.target.value获取表单输入值
console.log(e.target.value);
}
2、使用this.refs来获取值
给标签添加ref属性,在事件里通过this.refs.[属性].value来获取值
<input ref="val" onChange={this.refChange}/><button onClick={this.getRefVal}>通过ref获取输入框的值</button>
refChange=()=>{
//获取值
let str = this.refs.val.value;
this.setState({
val:str
})
}
3、event的部分事件
输入框事件:
onChange:输入框改变时触发
键盘事件:
onKeyUp:按键抬起时触发
onKeyDown:按键按下时触发
点击事件:
onClick:点击时触发
三、react的表单
1、双向数据绑定
双向数据绑定在vue中有,在react中是没有的,双向数据绑定就是双方的数据改变相互影响,下面只是模拟双向数据绑定:
//输入框使用value时需要添加onChange监听事件
//还可以使用defaultValue
<input value={this.state.data} onChange={this.inputDataChange} /><button onClick={this.getInputData}>改变model数据为data</button><br/>
数据显示:{this.state.data}<br/>
//初始化
constructor(props){
super(props);
this.state={
data:'data'
}
}
//输入框值改变时改变state的值,视图上相对改变
inputDataChange=(e)=>{
//此处是输入框状态改变的数据
this.setState({
data:e.target.value
})
}
//相当于state的值改变,视图上的值也改变
getInputData=()=>{
//此处是点击时要改变的数据
this.setState({
data:'data'
})
}
上面的的value需要事件监听,这里面有一个react的知识点:约束性组件和非约束性组件。
约束性组件,简单说就是react管理了它的value,而非约束性组件的value是由原生DOM管理的。
约束性组件是这样写的:
<input value={this.state.data} onChange={this.inputDataChange} />
这里的value属性不再是一个写死的值,它是this.state.data,而this.state.data是由this.inputDataChange这个监听事件负责管理的。
这个时候实际上 input 的 value 根本不是用户输入的内容。而是onChange 事件触发之后,由 this.setState 导致了一次重新渲染。不过React会优化这个渲染过程,实际它依然是通过设置input的value来实现的。
非约束性组件是这样写的:
<input defaultValue="a" />
这个defaultValue就是原生DOM中的value属性,其value值就是用户输入的内容,react不管理输入的过程。
对比约束性组件和非约束性组件的输入流程:
*约束性组件: 用户输入A -> 触发onChange事件 -> inputDataChange 中设置 state.name = “A” -> 渲染input使他的value变成A
*非约束性组件: 用户输入A -> input 中显示A
2、react表单的写法
这里介绍form表单里的几种常用的子标签:
一般表单都是需要用form标签包起来:
<form></form>
- 阻止表单的默认提交
有时我们需要阻止表单的默认提交,来自己把握什么时候提交调用preventDefault()方法,如下:
<form onSubmit={this.doSubmit}></form>
doSubmit=(e)=>{
//使用事件e来调 preventDefault()方法来阻止表单默认提交
e.preventDefault();
}
- 文本框
设置value属性,因为是约束性组件,所以需要onChange触发事件,下面的都是这样
在事件方法handleName(event)里使用event.target.value来获取输入框中的值,如下:
constructou(props){
super(props);
this.state={
name:''
}
}
handleName=(e)=>{
this.setState({
name:e.target.value
})
}
姓名:<input type="text" value={this.state.name} onChange={this.handleName} />
- 单选框
单选框非手动输入,所以需要在标签上加入value属性,否则获取不到数据。因为我们要选择,所以要添加checked,来判断选中状态:
constructou(props){
super(props);
this.state={
//默认选中女
sex:'0'
}
}
/**
checked={this.state.sex==0}是判断是否为选中状态
当点击选中按钮后获取当前选中的value值,然后改变sex的值
react重新渲染后,点击的按钮变为被选中状态
*/
handleSex=(e)=>{
this.setState({
sex:e.target.value
})
}
性别:<input type="radio" checked={this.state.sex==0} value="0" onChange={this.handleSex} />男
<input type="radio" checked={this.state.sex==1} value="1" onChange={this.handleSex} />女
- 下拉框
下拉框里的数据是数组,所以我们需要用到循环获取,我们需要有个变量city来存储选中的值,看代码:
constructou(props){
super(props);
this.state={
city:'',
citys:[
'北京','上海','深圳'
]
}
}
handleCity=(e)=>{
this.setState({
city:e.target.value
})
}
/**
使用map()来循环数据,注意map(function(value,key){})
的this的指向,此时的this是无法调用state的
注意:return中是需要一个根标签包裹的,此处<option>即可
需要在option上添加key,map循环需要,以便更好的管理数据
*/
城市:
<select value={this.state.city} onChange={this.handleCity}>
{this.state.citys.map(function(value,key){
return(
<option key={key} >{value}</option>
)
})}
</select>
- 复选框
constructou(props){
super(props);
this.state={
hobby:[
{'title':'睡觉','checked':true},
{'title':'吃饭','checked':false},
{'title':'听音乐','checked':false}
]
}
}
/**
hobby是个数组,我们通过key来找到选中状态,当点击时通过
hobby[key].checked = !hobby[key].checked;
来改变选中状态,然后将hobby重新赋值,和单选框类似
*/
handleHobby(key){
var hobby = this.state.hobby;
hobby[key].checked = !hobby[key].checked;
this.setState({
hobby:hobby
})
}
/**
因为我们需要key来找到选项的选中状态,所以我们需要把key传到方法中,
此处使用箭头函数将map函数中的this指向调整了,所以在return中可以是用this.handleHobby
*/
喜好:
{this.state.hobby.map((value,key)=>{
return(
<span key={key}>
<input type="checkbox" checked={value.checked} onChange={this.handleHobby.bind(this,key)}/>{value.title}
</span>
)
})}
- 文本域
和文本框类似:
constructou(props){
super(props);
this.state={
info:''
}
}
handleInfo=(e)=>{
this.setState({
info:e.target.value
})
}
info:<input type="textarea" value={this.state.info} onChange={this.handleInfo}/>
四、react中的state和props
props
1、react的组件从概念上看就是一个函数,可以接受一个参数最为输入值,这个参数就是props,可以把props理解为从外部传入组件内部的数据。
2、props经常被用作渲染组件和初始化状态,当一个组件被实例化之后,它的props是只读的,不可改变的。如果props在渲染过程中可以被改变,会导致这个组件显示的形态变得不可预测。只有通过父组件重新渲染的方式才可以把新的props传入组件中。
3、在组件中,我们最好为props中的参数设置一个defaultProps,并且制定它的类型。
state
一个组件的显示形态可以由数据状态和外部参数所决定,外部参数也就是props,而数据状态就是state
state的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。
写在最后:
- 如果文章中有错误或是表达不准确的地方,欢迎大家评论中指正,以便我完善。
- 文章我也会根据所学到新的知识不断更新。