草庐IT

react——事件绑定

夏*想想 2024-04-20 原文

        react有两种写法,一种是类组件,也叫有状态组件;一种是函数式组件,也叫无状态组件,而后引入了react hooks,函数式组件也能修改状态。在这两种组件中的事件绑定的原理一样,写法不一样。这篇文章主要就是记录这两种组件中的事件绑定写法。

 

一、前提说明

        重点是记录两种组件中事件绑定使用的区别,避免下次使用的时候还犯迷糊,在下面的写法中,可能出现同一类组件中多种写法,只要自己选择自己喜欢的那种写就可以了,没必要每种都要会,能看的懂就可以。想直接拿来用的,可以直接跳过原理,看使用案例,对原理感兴趣的可以回头来看看事件原理。在react中,事件的写法都是on+事件类型(第一个字母大写),如点击事件(onClick),鼠标事件(onMouseOver ,onMouseOut)

二、事件绑定的原理

        react中的事件都是合成事件,react并不是将click事件绑定到了div的真实DOM上,而是在document处监听了所有的事件,当事件发生并且冒泡到document处的时候,React将事件内容封装并交由真正的处理函数运行。这样的方式不仅仅减少了内存的消耗,还能在组件挂在销毁时统一订阅和移除事件。

        另外冒泡到document上的事件也不是原生的浏览器事件,而是由react自己实现的合成事件(SyntheticEvent)。因此我们如果不想要是事件冒泡的话调用event.stopProppagation()方法是无效的。而应该调用event.preventDefault()。

(一)事件注册

        组件更新或者装载时,在给dom增加合成事件时,需要将增加的target传入到document进行判断,给document注册原生事件回调为dispatchEvent(统一的事件分发机制)。

(二)事件存储

        EventPluginHub负责管理React合成事件的callback,它将callback存储到listennerBank中,另外还存储了负责合成事件的Plugin,Event存储到listennerbank中,每一个元素在listennerBank中会有唯一的key。

(三)事件触发执行

        点击时冒泡到docunment中,触发注册原生事件的回调dispatchEvent,获取到触发这个事件的最深层元素,事件执行利用react的批处理机制。

(四)合成事件

        循环所有类型的eventPlugin,对应每个事件类型,生成不同的事件池,如果是空,则生成新的,有则用之前的,根据唯一key获取到指定的回调函数,再返回带有参数的回调函数。

(五)总流程

 -- >  组件装载/更新

 -- >  新增/删除事件

 -- >  eventplugin添加到ListennerBank中监听事件

 -- >  触发事件

 -- >  生成合成事件

 -- >  通过唯一key获取到指定函数

 -->   执行指定回调函数

 -- >  执行完毕后释放

三、事件使用案例

(一)类组件的事件绑定

import React, { Component } from 'react'

export default class App1 extends Component {
    test2Fn() {
        console.log('test2');
    }
    test3Fn = () => {
        console.log('test3');
    }
    test4Fn = () => {
        console.log('test4');
    }
    render() {
        return (
            <div>
                {/* 直接写箭头函数,因为普通函数有this指向问题 */}
                <button onClick={() => { console.log('test1'); }}>第一种</button>
                {/* this.test2Fn()会被直接调用 和 this.test2Fn不一样*/}
                <button onClick={this.test2Fn}>第二种</button>
                <button onClick={this.test3Fn}>第三种</button>
                <button onClick={() => {
                    this.test4Fn()
                }}>第四种</button>

            </div>
        )
    }
}

个人比较喜欢第三种写法

第一种写法有弊端,逻辑长的时候不方便观看,也不建写在dom里面

第二种有this指向问题,如定义一个a=100,在方法二中通过this.a获取会报错,这是因为this没有指向App1实例中

 通过this.test2Fn.bind(this)可以解决,这样可以使两个this指向一致

import React, { Component } from 'react'

export default class App1 extends Component {
    a=100  //添加一个全局变量
    test2Fn() {
        console.log('test2',this.a);
    }
    test3Fn = () => {
        console.log('test3',this.a);
    }
    test4Fn = () => {
        console.log('test4',this.a);
    }
    render() {
        return (
            <div>
                {/* 直接写箭头函数,因为普通函数有this指向问题 */}
                <button onClick={() => { console.log('test1',this.a); }}>第一种</button>
                {/* this.test2Fn()会被直接调用 和 this.test2Fn不一样*/}
                <button onClick={this.test2Fn.bind(this)}>第二种</button>
                <button onClick={this.test3Fn}>第三种</button>
                <button onClick={() => {
                    this.test4Fn()
                }}>第四种</button>

            </div>
        )
    }
}

this指向修改

call:    修改this指向,并使函数自动执行(不用函数()调用)

apply: 修改this指向,并使函数自动执行(不用函数()调用)

bind:   修改this指向,需要手动执行(用()调用)

(二)函数式组件的事件绑定

function App2(){
    const test=()=>{
        console.log("add");
    }
    return(
        <div >
            <button onClick={test}>add</button>
        </div>
    )
}
export default App2

有关react——事件绑定的更多相关文章

  1. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  2. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  3. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  4. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

  5. ruby-on-rails - 在不重新查询数据库的情况下重新排序 Rails 中的事件记录? - 2

    例如,假设我有一个名为Products的模型,并且在ProductsController中,我有以下代码用于product_listView以显示已排序的产品。@products=Product.order(params[:order_by])让我们想象一下,在product_listView中,用户可以使用下拉菜单按价格、评级、重量等进行排序。数据库中的产品不会经常更改。我很难理解的是,每次用户选择新的order_by过滤器时,rails是否必须查询,或者rails是否能够以某种方式缓存事件记录以在服务器端重新排序?有没有一种方法可以编写它,以便在用户排序时rails不会重新查询结果

  6. ruby-on-rails - Ruby 长时间运行的进程对队列事件使用react - 2

    我有一个将某些事件写入队列的Rails3应用。现在我想在服务器上创建一个服务,每x秒轮询一次队列,并按计划执行其他任务。除了创建ruby​​脚本并通过cron作业运行它之外,还有其他稳定的替代方案吗? 最佳答案 尽管启动基于Rails的持久任务是一种选择,但您可能希望查看更有序的系统,例如delayed_job或Starling管理您的工作量。我建议不要在cron中运行某些东西,因为启动整个Rails堆栈的开销可能很大。每隔几秒运行一次它是不切实际的,因为Rails上的启动时间通常为5-15秒,具体取决于您的硬件。不过,每天这样做几

  7. ruby-on-rails - 使用 Rails 事件记录获取二级模型 - 2

    我有一个帖子属于城市的关系,城市又属于一个州,例如:classPost现在我想找到所有帖子及其所属的城市和州。我编写了以下查询来获取带有城市的帖子,但不知道如何在同一查找器中获取带有城市的相应州:@post=Post.find:all,:include=>[:city]感谢任何帮助。谢谢。 最佳答案 Post.all(:include=>{:city=>:state}) 关于ruby-on-rails-使用Rails事件记录获取二级模型,我们在StackOverflow上找到一个类似的问

  8. ruby - ruby 中绑定(bind)对象的实际使用 - 2

    昨晚,我在思考我认为是高级ruby​​语言的功能,即Continuations(callcc)和Bindingobjects。我的意思是高级,因为我有静态类型的oo语言背景(C#、Java、C++),我最近才发现ruby​​,所以这些语言特性对我来说不是很熟悉。我想知道这些语言功能在现实世界中的用途是什么。根据我的经验,一切都可以用静态类型的oo语言来完成,但有时我不太同意。我想我在阅读SamRuby的那篇好文章时发现了Continuation的美妙之处/兴趣:http://www.intertwingly.net/blog/2005/04/13/Continuations-for-C

  9. ruby - 在没有数据库的情况下伪造一个事件记录模型 - 2

    我觉得我错过了什么。我正在编写一个ruby​​gem,它允许与事件记录进行交互,作为其主要功能的附加功能。在为其编写测试用例时,我需要能够指定虚拟事件记录模型来测试此功能。如果我可以获得一个事件记录模型的实例,它不需要与数据库的任何连接,可以有关系,所有这些东西,但不需要我在数据库中设置表,那就太棒了。我对测试还很陌生,在Rails测试之外我也很陌生,但似乎我应该能够相当轻松地完成类似的事情,但我什么也没找到。谁能告诉我我错过了什么?我看过工厂、制造商、固定装置,所有这些似乎都想达到目标。人们如何在您只需要AR对象进行测试的地方测试gem? 最佳答案

  10. ruby-on-rails - 在事件记录库中添加某些方法的首选方法是什么? - 2

    我想创建一个模块,为从事件记录库继承的类提供一些通用方法。以下是我们可以实现的两种方式。1)moduleCommentabledefself.extended(base)base.class_evaldoincludeInstanceMethodsextendClassMethodsendendmoduleClassMethodsdeftest_commentable_classmethodputs'testclassmethod'endendmoduleInstanceMethodsdeftest_commentable_instance_methodputs'testinstanc

随机推荐