react-事件
宁静致远 7/19/2020 react
● 语法 on + 事件名称 = { 事件处理程序 } ,比如:<div onClick={ onClick }> ● 注意点 react事件采用驼峰命名法,比如:onMouseEnter、onFocus
- bind this
- event 参数
- 自定义事件传递参数
# bind this
this.handleClick = this.handleClick.bind(this)
事件绑定 this undefined
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return <div>
<button onClick={this.handleClick}>更新</button>
</div>
}
handleClick(){
console.log(this); // undefined
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
事件绑定时给方法bind(this)
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return <div>
// 每点击一次都要执行一次绑定
<button onClick={this.handleClick.bind(this)}>更新</button>
</div>
}
handleClick(){
console.log(this);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
构造函数中的给方法bind(this)
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
// 修改该方法的this 指向
// 初始化的时候就已经绑定
this.handleClick = this.handleClick.bind(this)
}
render(){
return <div>
<button onClick={this.handleClick}>更新</button>
</div>
}
handleClick(){
console.log(this);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
箭头函数
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return <div>
<button onClick={this.handleClick}>更新</button>
</div>
}
handleClick = () =>{
console.log(this);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
事件绑定时的匿名函数+箭头函数
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return <div>
<button onClick={() => this.handleClick()}>更新</button>
</div>
}
handleClick(){
console.log(this);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# event
重要:(react16 绑定到document, react17事件绑定到root)
React合成事件机制: React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。
若react事件绑定在真实的DOM节点上,一个DOM节点绑定过多事件处理函数,整个页面的响应和内存占用可能都会受到很大的影响。 React为了避免这类DOM事件的滥用,同时屏蔽底层不同浏览器之间的时间系统的差异,出现了一个中间层——SyntheticEvent。
- 当用户在为onClick添加函数时,React并没有将Click绑定到DOM上
- 而在document处监听所有支持的事件,当事件发生并冒泡至document(react16 绑定到document, react17事件绑定到root)处时,React将事件内容封装交给中间层 SyntheticEvent (负责所有事件合成)
- 然后使用统一的分发函数 dispatchEvent 将封装的事件内容交由真正的处理函数执行
- event 是 SyntheticEvent ,模拟出来 DOM 事件所有能力
- event.nativeEvent 是原生事件对象
- 所有的事件,都被挂载到 document 上 (react16 绑定到document, react17事件绑定到root)
- 和 DOM 事件不一样,和 Vue 事件也不一样
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
}
render(){
return <div>
<a href="http://www.baidu.com" onClick={this.handleClick}>百度链接</a>
</div>
}
handleClick = (event) => {
console.log(event); // 不是原生的event 是react 封装的 原生的event MouseEvent
event.preventDefault() // 阻止默认行为
event.stopPropagation() // 阻止冒泡
console.log('target', event.target); // 返回的是触发事件的节点元素 <a href="http://www.baidu.com">百度链接</a>
console.log('current target' , event.currentTarget); // 返回的是绑定事件的节点元素 <a href="http://www.baidu.com">百度链接</a>
// 获取原生的event
console.log(event.__proto__.constructor);
console.log('nativeEvent', event.nativeEvent)
console.log('nativeEvent target', event.nativeEvent.target) // 指向当前元素,即当前元素触发
console.log('nativeEvent current target', event.nativeEvent.currentTarget) // 指向 (react16 绑定到document, react17事件绑定到root)
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 自定义事件传递参数
箭头函数传参
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
this.state = {
name: 'zhangsan',
id: 1
}
}
render(){
return <div>
<button onClick={(e) => this.handleClick(this.state.name,this.state.id,e)}>点击</button>
</div>
}
handleClick (name,id,e) { // 传参最后一个参数追加event参数
console.log("name", name);
console.log("id", id);
console.log("e", e);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
bind传参
import React from 'react';
class EventComponent extends React.Component {
constructor(props){
super(props)
this.state = {
name: 'zhangsan',
id: 1
}
}
render(){
return <div>
<button onClick={this.handleClick.bind(this,this.state.name, this.state.id)}>点击</button>
</div>
}
handleClick (name,id,e) { // 传参最后一个参数追加event参数
console.log("name", name);
console.log("id", id);
console.log("e", e);
}
}
export const EventDemo = EventComponent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 函数式获取事件对象
获取事件对象e只需要在 事件的回调函数中 补充一个形参e即可拿到
// 函数组件
function HelloFn () {
// 定义事件回调函数
const clickHandler = (e) => {
console.log('事件被触发了', e)
}
return (
// 绑定事件
<button onClick={clickHandler}>click me!</button>
)
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 函数式传递额外参数
造事件绑定为箭头函数 在箭头函数中完成参数的传递
import React from "react"
// 如何获取额外的参数?
// onClick={ onDel } -> onClick={ () => onDel(id) }
// 注意: 一定不要在模板中写出函数调用的代码 onClick = { onDel(id) } bad!!!!!!
const TestComponent = () => {
const list = [
{
id: 1001,
name: 'react'
},
{
id: 1002,
name: 'vue'
}
]
const onDel = (e, id) => {
console.log(e, id)
}
return (
<ul>
{list.map(item =>(
<li key={item.id}>
{item.name}
<button onClick={(e) => onDel(e, item.id)}>x</button>
</li>
))}
</ul>
)
}
function App () {
return (
<div>
<TestComponent />
</div>
)
}
export default App
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 类组件的事件绑定
// 类组件中的事件绑定
// 整体的套路都是一致的 和函数组件没有太多不同
// 唯一需要注意的 因为处于class 类环境下 所以定义事件回调函数 以及 绑定它写法上有不同
// 定义的时候: class Fields语法
// 使用的时候: 需要借助this关键词获取
// 注意事项: 之所以要采取class Fields写法是为了保证this的指向正确 永远指向当前的组件实例
import React from "react"
class CComponent extends React.Component {
// class Fields
clickHandler = (e, num) => {
// 这里的this指向的是正确的当前的组件实例对象
// 可以非常方便的通过this关键词拿到组件实例身上的其他属性或者方法
console.log(this)
}
clickHandler1 () {
// 这里的this 不指向当前的组件实例对象 undefined 存在this丢失问题
console.log(this)
}
render () {
return (
<div>
<button onClick={(e) => this.clickHandler(e, '123')}>click me</button>
<button onClick={this.clickHandler1}>click me</button>
</div>
)
}
}
function App () {
return (
<div>
<CComponent />
</div>
)
}
export default App
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43