React 事件踩坑(一)

问题描述

今天想要用react实现一个对话框的功能,这个对话框有一个特点就是在点击这个对话框的时候直接就能够使它隐藏,并且在对话框之外的任何东西都是可以点击的,并且能够及时的响应。比如下面的登陆对话框,我们在点击header上面的menu button的时候能够在显示left menu的同时将对话框给隐藏起来。

这里写图片描述

实现思路

实现思路很简单,就是在document.body上绑定一个click事件隐藏对话框,在对话框上绑定一个click事件来阻止自己的click的事情冒泡到document.body上。具体的实现代码如下:

class Dialog extends React.Component {
    constructor(...props){
        super(...props);

        [
            '_onBlurHandler',
            '_onClickHandler',

        ].forEach(func=>{
            this[func] = this[func].bind(this);
        });
    }

    _onBlurHandler(e){
        this.props.onBlur && this.props.onBlur(e);
    }

    _onClickHandler(e){
        e.nativeEvent.stopPropagation();
    }

    componentDidMount(){
        document.body.addEventListener('click', this._onBlurHandler, false);

    }

    componentWillUnmount(){
        document.body.removeEventListener('click', this._onBlurHandler, false);
    }


    render(){
        const className = [
            'dialog',
            this.props.className,   

        ].join(' ');

        return (
           <div 
              className={className}
              onClick={this._onClickHandler}>
              {this.props.children}
           </div>
        );
    }
}

Dialog.propTypes = {
    onBlur: React.PropTypes.func
};

好简单有没有,在实现之前把宝宝乐的,so easy。可是实现调试缺吓死抱抱了,为毛点击dialog的时候,dialog会触发document.body上绑定的click事件呢 ?

问题分析及解决

按理论上说上面没有问题呀,怎么可能会错呢,好吧我们还是好好的调试一下吧,我们先来看一下dialog上面绑定的Click事件有哪些?

这里写图片描述

哎,怎么有两个事件呢,而且都是代理在document上,我们绑定的事件呢?其实很简单了,对于react的事件,不是直接绑定在元素上的,而是代理给document,这样做是为了提高效率。然后我们仔细想想为什么我们出错了,因为我们的事件是绑定在document.body上面的,所以在点击的时候,事件先冒泡给body,可是这样会触发_onBlurHandler函数的调用,这个函数中我实现了一个隐藏对对话框的功能,所以导致我结果错了。知道原因那个就好办了,把document.body换成document不就可以了的,哈哈,我是天才有没有。

componentDidMount(){
        document.addEventListener('click', this._onBlurHandler, false);
    }

    componentWillUnmount(){
        document.removeEventListener('click', this._onBlurHandler, false);
    }

赶快调试一下能不能正常工作,我去,怎么又出上了问题,对话框还是消失了。怎么回事呀,不是应该没问题了吗,问题又在哪里了,哎,心塞。

仔细想一下,因为事件都是绑定在document上的,那么上面阻止冒泡的代码不是没有用了,那我们应该怎么解决呢,哈哈哈,也很简单,其实就是把stopPropagation换成stopImmediatePropagation就行了,这两个函数的区别在于stopImmediatePropagation会在调用对应的回调函数之后屏蔽对应元素对应事件所有回调函数的调用,并且禁止冒泡,而stopPropagation函数只屏蔽冒泡,并不屏蔽自身的事件。

好了,调试一下,啊哈哈哈哈,终于成功了。发现react的坑还是蛮多的,慢慢踩吧,每天进步一点。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
React使用useState是非常常见的,它让我们能够在函数组件添加状态。然而,有一些常见的陷阱需要注意。下面是一些指南: 1. 错误使用数组解构:当使用数组解构语法来访问useState返回的数组时,确保你使用正确的索引位置。例如,如果你使用了多个useState,确保你在解构时使用正确的索引。否则,你可能会将状态值分配给错误的变量。 2. 对象与合并:当你使用对象作为useState的初始值时,记住useState并不会自动将新的对象与旧的对象合并。相反,它会直接替换整个对象。所以,如果你想保留旧对象的内容并仅更新其的一部分,你需要手动进行合并。 3. 引用相等性:React使用引用相等性来检测状态的更改。这意味着如果你在更新状态时返回相同的引用,React不会触发重新渲染。因此,确保在更新状态时返回新的引用,而不是直接修改现有对象。 4. 异步更新:当在事件处理程序或异步函数更新状态时,记得useState是异步的。这意味着多个setState调用可能会被合并在一起,而不是立即更新。如果你需要基于当前状态进行计算,请使用回调函数形式的setState,以便正确地捕获先前的状态。 5. 多个useState:当在一个组件使用多个useState时,确保给每个useState调用一个有意义的名称。这样可以使代码更清晰,易于理解和维护。 6. 无限循环:在使用useState时,一定要小心避免进入无限循环。例如,如果你在组件的渲染阶段内调用了useState,可能会导致无限循环的情况。解决这个问题的方法是确保条件语句正确地包裹useState的调用。 希望这些指南能够帮助你避免在使用useState时遇到的常见问题!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值