react随笔5 事件处理

事件处理

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   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  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  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  onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容