美文网首页
react随笔5 事件处理

react随笔5 事件处理

作者: _fan凡 | 来源:发表于2019-04-21 20:56 被阅读0次

    事件处理

    React元素的事件处理和DOM元素的事件处理很相似,但是有一点语法上的不同:

    • React事件绑定属性的命名采用驼峰式写法,而不是小写(DOM元素写法)。
    • 如果采用了JSX的语法,需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素写法)
      比如:传统的HTML:
    <button onclick="activateLasers()">Activate Lasers</button>
    

    React中写法:

    <button onClick={activateLasers}>Activate Lasers</button>
    

    可以看到,传统HTML中点击事件的属性名是小写的onclick,而React中是驼峰式的onClick;点击事件的值,传统的HTML中是一个字符串,字符串的值就是处理函数的名称:activateLasers(),而React中采用的JSX语法,点击事件的值就是这个函数名称:activateLasers

    • React(从版本v0.14开始)中不能使用返回false的方式组织默认行为。必须使用事件的preventDefault函数,传统的HTML就可以直接返回false
      比如,传统的HTML组织链接默认打开一个新页面:
    <a href="https://react.docschina.org/docs/handling-events.html"  onclick="console.log('The line was clicked');return false">
    Click me </a>
    

    这样点击链接Click me时,会在控制台输出The line was clicked,但是不会打开新的url地址https://react.docschina.org/docs/handling-events.html
    在React中,直接返回false是不行的。需要显示调用出发事件的preventDefault函数:

    function ActionLink() {
      function handleClick(e) {
        e.preventDefault();
        console.log('The line was clicked');
      }
      
      return (
        <a href="https://react.docschina.org/docs/handling-events.html" onClick=  
                {handleClick} >Click me </a>
      );
    }
    
    ReactDOM.render(
      <ActionLink />, document.getElementById('root')
    );
    

    这里是使用函数式组件演示的,可以直接拷贝代码在这里测试。记得把上边的代码copy到JS框中,如下图:

    image.png
    上面是React使用函数组件来实现的,如果使用类组件,则如下:
    class ActionLink extends React.Component {
       constructor(props) {
         super(props);
         this.handleClick = this.handleClick.bind(this);
       }
      
       handleClick(e) {
         e.preventDefault();
         console.log('The line was clicked');
       }
      
      render () { 
        return (<a href="https://react.docschina.org/docs/handling-events.html" onClick={this.handleClick}>Click me </a>);
      };
    }
    ReactDOM.render(
      <ActionLink />, document.getElementById('root')
    ); 
    

    结果如下:


    image.png

    在这里,e是一个合成事件。React根据W3C spce来定义这些合成事件。更多事件参考SyntheticEvent
    使用React的时候通常不需要为DOM元素添加监听器,如使用addEventListener方法。仅仅需要在元素初始化的时候提供一个监听器。
    我们也看到了,使用函数组件和类组件,事件处理函数在语法上有点区别。使用函数组件的时候,事件处理函数还是像普通的函数一样声明function handleClick() {},但是使用类组件的时候,时间处理函数就是类的一个方法,所以在定义的时候是handleClick(){},没有使用function关键字了。
    我们还发现,在使用类组件的时候,在构造函数中有这么一句代码:

    this.handleClick = this.handleClick.bind(this);
    

    在render方法的返回元素中,onClick属性的值,我们使用的是JSX语法:onClic={this.handleClick},也就是点击事件的处理函数是this的handleClick方法,this代表的是当前组件。也就是点击事件其实是回调的this的handleClick方法,我们必须谨慎对待JSX回调函数中的this,类的方法默认是不会绑定this的,如果没有如上的绑定代码,即没有绑定this.handleClick,那么在handleClick这个方法中使用this的话,就会报错,this提示是undefined:如下:

    image.png
    这并不是React的特殊行为,他是函数如何在JavaScript中运行的一部分。如果没有在方法后面添加(),例如onClick={this.handleClick},那就需要在constructor方法中为handleClick这个方法绑定this。当然可以在后边机上(),但是这样在初始化的时候就直接执行了,达不到我们想要的效果,图下图:
    image.png
    如果不想使用绑定,还有另外两种解决方式:
    • 1.使用实验性的属性初始化器语法
    class ActionLink extends React.Component {
      handleClick = () => {
        console.log(this);
      }
    
      render() {
        return (<a href="#" onClick={this.handleClick}>click me</a>);
      }
    }
    

    如下图:


    image.png
    • 2.在回调函数中使用箭头函数
    class ActionLink extends React.Component{
      handleClick(e) {
        console.log(e);
        console.log(this);
      }
      
      render(){
        return (<a href="#" onClick={(e) => this.handleClick(e)}></a>);
      }
    }
    

    如下图:

    image.png
    注意:使用这个语法有个问题,每次组件有变化需要重新渲染的时候,都会创建一个不同的回调函数。在多数情况下,没有问题。但是如果这个回调函数作为一个属性值传入低阶组件,那么这些组件可能会进行额外的重新渲染。

    向事件处理程序传递参数

    通常我们会给事件处理程序传递额外的参数,进行不同的操作。例如,若是id是我们需要删除的那一行数据的id,那么以下两种穿残方式度可以:

    <a onClick={(e) => this.handleClick(id, e)}>Delete Row</a>
    <a onClick={this.handleClick.bind(this, id)}> Delete Row</a>
    

    上述两种方法是等价的。但是需要注意的是,在使用箭头函数arrow functions的形式进行回调的时候,参数e作为React时间对象是作为第二个参数进行传递的,也就是时间独享必须显示的进行传递。但是通过bind的方式,事件对象以及更多的参数是被隐式的进行传递的。
    但是通过bind方式向时间处理程序传递参数的时候,如果在事件处理程序中使用到了事件对象本身e,那么在函数定义的时候,e必须是作为参数列表的最后一个参数:

    class Popper extends React.Component{
        constructor(){
            super();
            this.state = {name:'Hello world!'};
        }
        
        preventPop(name, e){    //事件对象e要放在最后
            e.preventDefault();
            alert(name);
        }
        
        render(){
            return (
                <div>
                    <p>hello</p>
                    {/* Pass params via bind() method. */}
                    <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
                </div>
            );
        }
    }
    

    相关文章

      网友评论

          本文标题:react随笔5 事件处理

          本文链接:https://www.haomeiwen.com/subject/cgdjgqtx.html