# react合成事件

# 首先来复习一下JS原生DOM事件绑定的三种方式:

1】直接在标签属性绑定事件

  • 需要在标签属性中立即执行绑定的函数
  • 可以直接return false;进行阻止默认事件
  • 没有event对象
<div id="btn" onclick="clickone();return false;"></div> //直接在DOM里绑定事件,需要写成立即执行的格式
<script>
   function clickone(){ alert("hello"); }
</script>

2】通过获取DOM绑定事件

  • 在脚本中通过匿名函数的方式绑定的只会执行最后一个事件。
  • 也可以使用return false;进行阻止默认事件。也可以使用e.preventDefault()
<div id="btn"></div>
<script>
  document.getElementById("btn").onclick = function(e){
    //e.preventDefault()
    alert("hello");
    return false
  }
</script>

3】添加事件监听函数

  • 用 "addEventListener" 可以绑定多次同一个事件,且都会执行,
  • 而在DOM结构如果绑定两个 "onclick" 事件,只会执行第一个;
  • 只能通过e.preventDefault()阻止默认事件
<div id="btn"></div>
<script>
  document.getElementById("btn").addeventlistener("click",(e)=>{
    e.preventDefault()//阻止默认事件
    alert("hello")
  },false); 
</script>

# React合成事件理解:

参考资料:

React 合成事件和原生事件的区别

React合成事件和DOM原生事件混用须知

react使用的是JSX语法,驼峰命名法,所以这里是事件onClick。

<div className="testDom" onClick={this.testDomClick}><div>

# React合成事件和原生事件区别:

React合成事件一套机制:React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给SyntheticEvent函数处理、运行和处理。

如果DOM上绑定了过多的事件处理函数,整个页面响应以及内存占用可能都会受到影响。React为了避免DOM事件滥用,同时屏蔽底层不同浏览器之间的事件系统差异,实现了一个中间层——SyntheticEvent

(类似于用中间层来事件委托)

  1. 冒泡到document顶层
    • 当用户在为onClick添加函数时,React并没有将Click事件绑定在DOM上面。
  2. 封装所有事件给SyntheticEvent事件合成(负责所有事件合成)
    • 而是在document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装交给中间层SyntheticEvent(负责所有事件合成)
  3. 函数dispatchEvent统一分发
    • 所以当事件触发的时候,对使用统一的分发函数dispatchEvent将指定函数执行。

# React中使用原生事件:

由于原生事件需要绑定在真实DOM上,所以一般是在componentDidMount阶段/ref的函数执行阶段进行绑定操作,在componentWillUnmount阶段进行解绑操作以避免内存泄漏。

示例如下:

class Demo extends React.PureComponent {
    componentDidMount() {
        const $this = ReactDOM.findDOMNode(this)
        $this.addEventListener('click', this.onDOMClick, false)
    }

    onDOMClick = evt => {
        // ...
    }

    render() {
        return (
            <div>Demo</div>
        )
    }
}

原生事件和react合成事件混合使用注意:

  • 响应顺序(原生事件一般情况执行顺序先于react合成事件)
  • 如果我们在原生事件中使用e.stopPropagation()进行阻止冒泡事件,可能会影响react合成事件的先外层冒泡,而导致错误

# 示例:

import React, { Component } from 'react'

export default class Event extends Component {
    componentDidMount() {
        const $this = this.refs.button
        $this.addEventListener('click', this.onDOMClick, false)
    }

    onDOMClick = evt => {
        console.log('dom event')
    }

    onClick = evt => {
        console.log('react event')
    }

    render() {
        return (
            <div ref='button' onClick={this.onClick}>Demo</div>
        )
    }
}

执行结果:dom event react event(原生事件先于react合成事件执行)

如果我们现在将原生事件进行e.stopPropagation阻止冒泡,则必将影响react合成事件不能顺利执行。(注意在react合成事件中是不能进行阻止冒泡操作的。)

import React, { Component } from 'react'

export default class Event extends Component {
    componentDidMount() {
        const $this = this.refs.button
        $this.addEventListener('click', this.onDOMClick, false)
    }

    onDOMClick = evt => {
        evt.stopPropagation()
        console.log('dom event')
    }

    onClick = evt => {
        console.log('react event')
    }

    render() {
        return (
            <div ref='button' onClick={this.onClick}>Demo</div>
        )
    }
}

此时只打印出:dom event,因为react合成事件的事件冒泡被影响了,没有顺利冒泡到document上面进行委托统一分发。

Last Updated: 8/1/2021, 1:43:20 PM