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

事件绑定时给方法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

构造函数中的给方法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

箭头函数

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

事件绑定时的匿名函数+箭头函数

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

# 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 将封装的事件内容交由真正的处理函数执行
  1. event 是 SyntheticEvent ,模拟出来 DOM 事件所有能力
  2. event.nativeEvent 是原生事件对象
  3. 所有的事件,都被挂载到 document 上 (react16 绑定到document, react17事件绑定到root)
  4. 和 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

# 自定义事件传递参数


箭头函数传参

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

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

# 函数式获取事件对象


获取事件对象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

# 函数式传递额外参数


造事件绑定为箭头函数 在箭头函数中完成参数的传递


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

# 类组件的事件绑定


// 类组件中的事件绑定
// 整体的套路都是一致的 和函数组件没有太多不同
// 唯一需要注意的 因为处于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
更新: 8/19/2022, 2:56:36 PM