目录
一、React的事件处理
1、与DOM事件处理的不同之处
(1)React事件的命名方式:小驼峰方式,DOM的命名方式是小写
(2)事件处理函数是以对象的方式赋值,而不是以字符串的方式赋值
(3)阻止默认事件的方式不同
2、React中事件处理函数的定义
(1)使用ES6的箭头数
(2)在构造函数中进行绑定:将事件处理函数作为类的成员函数
(3)在render函数中绑定this
(4)React中事件处理函数
(5)注意事项
3、事件处理中的参数传递
(1)直接传递参数
(2)在定义UI控件时使用data自定义属性,在事件处理函数中通过'e.target.dataset.属性名'来获取UI控件中的data属性值
4、事件流
(1)React的事件流默认是冒泡
(2)React中使用捕获方式:事件类型后面加一个后缀Capture
5、事件对象
(1)在React事件处理中有一个全局事件对象
(2)在异步操作中获取event
一、React的事件处理
1、与DOM事件处理的不同之处
(1)React事件的命名方式:小驼峰方式,DOM的命名方式是小写
例如:DOM的命名:onclick
React的命名:onClick
(2)事件处理函数是以对象的方式赋值,而不是以字符串的方式赋值
例如:DOM以字符串方式:onclick = "handleClick()"
React以对象方式:onClick = { handleClick }
(3)阻止默认事件的方式不同
DOM通过返回false来阻止: <a href="www.baidu.com" οnclick="javascript:return false;">百度</a>
React需要显式调用e.preventDefault来阻止
2、React中事件处理函数的定义
(1)使用ES6的箭头数
①在render函数中使用箭头函数:
Ⅰ、优点:不用在构造函数中绑定this
Ⅱ、缺点:当函数的逻辑比较复杂时,render就显得臃肿,无法直观的看到组件的UI结构,代码可读性差
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件处理函数-->在render中使用箭头函数</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.创建一个类组件
class MyComponent extends React.Component{
constructor(props){
super(props)
this.state={
msg: '小森同学'
}
}
render(){
return (
<div>
<button onClick= { ()=>{ console.log(this.state.msg)} } >点我</button>
</div>
)
}
}
//2.进行渲染
ReactDOM.render(<MyComponent/>,root)
</script>
</body>
</html>
②使用class fields语法:将箭头函数赋给类的属性
Ⅰ、优点:不用在构造函数中绑定this,在render函数中调用简单
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.创建一个类组件
class MyComponent extends React.Component{
constructor(props){
super(props)
this.state={
msg: '小沈同学',
number: 0
}
}
handleClick = ()=>{ //将箭头函数赋给类的属性
console.log(this.state.msg) //将一个箭头函数赋值为handleClick,handleClick是MyComponent的一个属性
}
render(){
console.log('render')
return (
<div>
<button onClick= { this.handleClick } >点我</button> //调用这个属性
</div>
)
}
}
//2.进行渲染
ReactDOM.render(<MyComponent/>,root)
</script>
</body>
(2)在构造函数中进行绑定:将事件处理函数作为类的成员函数
注意:在定义事件处理函数时,是无法识别this(即this是undefined的),必须在构造函数中绑定this
①、优点:在render函数调用时不需要重新创建事件处理函数
②、缺点:当事件处理很多时,构造函数就显的很繁琐
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.创建一个类组件
class MyComponent extends React.Component{
constructor(props){
super(props)
this.state={
msg: '小沈同学',
number: 0
}
this.add = this.add.bind(this) //this指针绑定到函数add里面去
}
handleClick = ()=>{
console.log(this.state.msg)
}
add(){ //如果上述不绑定this,那么add函数里的this将无法识别
let num = this.state.number
num++
this.setState({
number: num
})
console.log(this.state.number)
}
render(){
console.log('render')
return (
<div>
<button onClick= { this.handleClick } >点我</button>
<button onClick= { this.add }>Number++</button>
</div>
)
}
}
//2.进行渲染
ReactDOM.render(<MyComponent/>,root)
</script>
</body>
(3)在render函数中绑定this
①、优点:在调用事件处理函数时,传参比较方便
②、缺点:每次调用render函数时都重新绑定,导致性能下降
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.创建一个类组件
class MyComponent extends React.Component{
constructor(props){
super(props)
this.state={
msg: '小沈同学',
number: 0
}
// this.add = this.add.bind(this) //this指针绑定到函数add里面去
}
handleClick = ()=>{
console.log(this.state.msg)
}
add(){ //如果上述不绑定this,那么add函数里的this将无法识别
let num = this.state.number
num++
this.setState({
number: num
})
console.log(this.state.number)
}
render(){
console.log('render')
return (
<div>
<button onClick= { this.handleClick } >点我</button>
<button onClick= { this.add.bind(this) }>Number++</button>
</div>
)
}
}
//2.进行渲染
ReactDOM.render(<MyComponent/>,root)
</script>
</body>
(4)React中事件处理函数
几种方式的比较
影响 | constructor函数中bind | 使用class fields语法 | render中使用箭头函数 | render中使用bind | render时生成新函数 | 否 | 否 | 是 | 是 | 性能 | 无影响 | 无影响 | 有影响 | 有影响 | 可直接携带参数 | 否 | 否 | 是 | 是 | 简洁性 | 不好 | 好 | 好 | 好 |
(5)注意事项
①React事件的命名采用小驼峰式(camelCase),而不是纯小写。且事件名称之后不能加(),否则会直接执行
②不能通过返回false的方式阻止默认行为,必须显示的使用preventDefault
③必须谨慎对待JXS回调函数中的this,在JavaScript中,class(类)的方法默认不会绑定this。如果忘记绑定this.textChange并把它传入onChange,当调用这个函数的时候,this的值为undefined。如果觉得使用bind麻烦,还可以使用箭头函数。
3、事件处理中的参数传递
(1)直接传递参数
①在构造函数中给事件处理函数绑定this,调用事件处理函数时直接传参
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.定义类组件
class Clock extends React.Component{
constructor(props){
super(props)
this.state= {
list:[
{
id: 111,
msg: '小森'
},
{
id: 222,
msg: '小沈'
},
{
id: 333,
msg: '小顾'
}
],
msg: '编号:'
}
this.handleClick = this.handleClick.bind(this)
}
handleClick(id){ //事件处理函数
alert("编号:"+id)
}
render(){
//获取状态属性值
const { list } = this.state
return (
<div>
{
list.map((item)=>
<button onClick={ ()=>{this.handleClick(item.id)}} key={item.id}>{item.msg}</button>
)
}
</div>
)
}
}
//2.渲染
ReactDOM.render(<Clock/>,root)
</script>
??? ? ? ??注意:在箭头函数中调用事件处理函数时不需要绑定this
②在render函数中调用事件处理函数时进行this的绑定
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.定义类组件
class Clock extends React.Component{
constructor(props){
super(props)
this.state= {
list:[
{
id: 111,
msg: '小森'
},
{
id: 222,
msg: '小沈'
},
{
id: 333,
msg: '小顾'
}
],
msg: '编号:'
}
}
handleClick(id){ //事件处理函数,e表示触发事件的对象,成员函数
let str = this.state.msg
alert(str + id)
}
render(){
//获取状态属性值
const { list } = this.state
return (
<div>
{
list.map((item)=>
<button onClick={ this.handleClick.bind(this,item.id) } key={item.id}>{ item.msg }</button>
)
}
</div>
)
}
}
//2.渲染
ReactDOM.render(<Clock/>,root)
</script>
(2)在定义UI控件时使用data自定义属性,在事件处理函数中通过'e.target.dataset.属性名'来获取UI控件中的data属性值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件处理中的参数传递</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root');
//1.定义类组件
class Clock extends React.Component{
constructor(props){
super(props)
this.state= {
list:[
{
id: 111,
msg: '小森'
},
{
id: 222,
msg: '小沈'
},
{
id: 333,
msg: '小顾'
}
],
msg: '编号:'
}
}
handleClick(e){ //事件处理函数,e表示触发事件的对象
let str = this.state.msg
alert(str + e.target.dataset.count)
//事件处理对象event,通过event可以得到target目标对象,就是那个button。dataset,得到自定义属性的集合,在集合里找到count
}
render(){
//获取状态属性值
const { list } = this.state
return (
<div>
{
list.map((item)=>
<button
onClick={ this.handleClick.bind(this) }
key={item.id}
data-count = { item.id} //标签的自定义属性用'data-'开头后跟自定义属性名
>{ item.msg }</button>
)
}
</div>
)
}
}
//2.渲染
ReactDOM.render(<Clock/>,root)
</script>
</body>
</html>
4、事件流
(1)React的事件流默认是冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件流</title>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
//1.定义CSS样式
const style = {
child: {
width: '100px',
height: '100px',
backgroundColor: 'red'
},
parent: {
width: '150px',
height: '150px',
backgroundColor: 'blue'
},
ancestor: {
width: '200px',
height: '200px',
backgroundColor: 'green'
}
}
//2.定义类组件
class App extends React.Component{
render(){
return (
<div
onClick= { ()=>{ console.log('ancestor')}}
style = { style.ancestor }
>
<div
onClick={ ()=>{ console.log('parent')}}
style = { style.parent }
>
<div
onClick={ (e)=>{
console.log('child')
e.stopPropagation() //阻止冒泡
}}
style = {style.child }
>
</div>
</div>
</div>
)
}
}
//3.渲染
ReactDOM.render(<App/>,root)
</script>
</body>
</html>
//输出child,parent,ancestor
(2)React中使用捕获方式:事件类型后面加一个后缀Capture
先由document找到最外层绿色的,然后传给蓝色,然后传给红色。所以工具中输出的顺序是(ancestor,parent,child)
5、事件对象
虽然React事件是合成事件,但是在事件处理中可以获取事件对象的
(1)在React事件处理中有一个全局事件对象
event对象,每次事件触发后(事件处理函数调用完成后),就会清空event对象当下一次事件触发时重新获取该对象。该对象不是原生(DOM)的event对象,但是可以通过该对象获取原生对象的部分属性
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
//1.定义样式规则
const style = {
"mydiv": {
width: '150px',
height: '150px',
backgroundColor: 'red'
}
}
//2.定义类组件
class App extends React.Component{
constructor(props){
super(props)
this.state = {
x: 0,
y: 0
}
}
render(){
return (
<div>
<div style = { style['mydiv']} //以数组的方式设置样式
onClick= { (event)=> { //'event'对象不是原生的event,但是可以通过event来获取原生的事件对象的部分属性
const { clientX,clientY } = event
this.setState({
x: event.clientX,
y: event.clientY
})
>
X: {this.state.x},Y: { this.state.y }
</div>
</div>
)
}
}
//3.渲染
ReactDOM.render(<App />,root)
</script>
(2)在异步操作中获取event
?问题:当事件触发、响应结束后,event对象会被清空,但是异步数据还没有得到,在得到异步数据之后再去访问?event对象的属性就会报错。
解决办法:先将event对象的某些属性值保存起来,得到异步数据之后再来使用这些属性值
<div id="root"></div>
<script type="text/babel">
let root = document.getElementById('root')
//1.定义样式规则
const style = {
"mydiv": {
width: '150px',
height: '150px',
backgroundColor: 'red'
}
}
//2.定义类组件
class App extends React.Component{
constructor(props){
super(props)
this.state = {
x: 0,
y: 0
}
}
render(){
return (
<div>
<div style = { style['mydiv']} //以数组的方式设置样式
onClick= { (event)=> { //'event'对象不是原生的event,但是可以通过event来获取原生的事件对象的部分属性
const { clientX,clientY } = event //定义变量,将event保存起来
setTimeout(()=>{ //下次触发时就可以得到保存在变量中的值
this.setState({
x: clientX,
y: clientY
})
},1000)
}}
>
X: {this.state.x},Y: { this.state.y }
</div>
</div>
)
}
}
//3.渲染
ReactDOM.render(<App />,root)
</script>
|