react随笔5 事件处理

事件处理

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

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

React中写法:


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

  • React(从版本v0.14开始)中不能使用返回false的方式组织默认行为。必须使用事件的preventDefault函数,传统的HTML就可以直接返回false
    比如,传统的HTML组织链接默认打开一个新页面:

Click me 

这样点击链接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 (
    Click me 
  );
}

ReactDOM.render(
  , 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 (Click me );
  };
}
ReactDOM.render(
  , 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 (click me);
  }
}

如下图:


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

如下图:

image.png

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

向事件处理程序传递参数

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

 this.handleClick(id, e)}>Delete Row
 Delete Row

上述两种方法是等价的。但是需要注意的是,在使用箭头函数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 (
            

hello

{/* Pass params via bind() method. */} Click
); } }

你可能感兴趣的:(react随笔5 事件处理)