React-事件处理详解

2023-11-15

对于用户界面而言,展示只占整体设计因素的一半,另一半则是相应用户输入,即通过JavaScript处理用户产生的事件。

React通过将事件处理器绑定到组建上处理事件,事件触发的同时更新组建的内部状态,内部状态更新会触发组件的重绘。因此,如果视图层想要渲染出事件出发后的结果,它所要做的就是渲染函数中读取组件的内部状态。

一、绑定事件处理器

React处理事件本身和原生的JavaScript事件一样:MouseEvents事件用于点击处理器,Change事件用于表单元素变化,等等,所有事件在命名上与原生的JavaScript规范一致,并且会在相同的情境下被触发,React绑定事件处理器的语法和HTML语法非常相似。比如,在我们的问卷制作工具实例中,包含了下面的代码,在Save按钮上绑定onclick事件处理器。

<button className ='btn btn-save'onClick={this.handleSaveClicked}>Save</button>

 

用户点击这个按钮时,组件的handleSaveClicked方法会被调用。这个方法中包含处理Save行为的逻辑。

 

PS:这个代码可在写法上类似普通不推荐的HTML内联事件处理器属性,比如:onClick,但其实在底层实习那上冰没有使用HTMLonClick属性。React只是用这种写法绑定事件处理器,但内部则是按照需要高效的维护着时间处理器。

如果不用JSX语法,你可以选择在参数对象的属性上指定事件处理器,比如:

React.DOM.button({ClassName:'btnbtn-save',onClick:this.handleSaveClicked},"Save");

其中大部分事件不需要而外的处理就可以工作,但是触控事件需要通过调用一下代码手动启动:

React.initializeTouchEventtrue);

 

二、事件和状态

1、设想你需要让一个组件随着用户的输入而改变,比如在问卷编辑器中,你想要让用户从一个问题类型的菜单当中拖拽问卷问题。

首先,在渲染函数内部基于HTML5拖放(Drag and DropAPI注册事件处理器,代码如下:

var SurveyEdit =React.creatclass{
 

renderfunction(){
     <div className='survey-edit'>

<div className='row'>

<aside className='sidebar col-md-3'>

<h2>Module</h2>

<DraggableQuestions>

</aside>

<div className='survey-canvas col-md-9'>

    <div

className ={'drop-zone well well-drop-zone'}

onDragOver={this.handleDragOver}

onDragEnter={this.handleDragEnter}

onDragLeave={this.handleDragLeave}

onDrop ={this.handleDrop}

>

Drag and drop a module from the left

</div>

 

</div>

 

</div>

    </div>

}

});

 

三、根据状态进行渲染

事件处理器方法还需要完成一件事——展开当前已经加入的题目清单。为了实现该功能,你需要充分利用每个React组件的内部状态,组件默认是null,但是可以通过它的getInitialState方法将其出事话为合理的值,比如:

getInitaSatefunciton (){

return  {

dropZoneEntered:false

title:’‘,

introduction' ',

quesions:【】

}

}

以上代码组件初始化了默认值:一个空标题、一个空的介绍、一组空的题目以及一个值为falsedropZoeEntered属性,用于表示当前用户没有拖拽任何内容那个到放置区域。

到这里,你已经可以在render方法当中读取this.state,以便向用户展示当前表单中所有数据了。

 

四、更新状态

更新组件内部状态会出发组件重绘,所以接下来要做的事情就是在拖拽的事件处理器方法中更新状态,然后再次运行render函数,它会从this.state中读取新数据来显示标题,介绍及题目,用户会看到所有内容被正确的更新。

更新组件状态有两种方案:组件的setState方法和repaceState方法。replaceState用一个全新的state对象完整的替换掉原有的state。使用不可变数据结构表示状态时,这种方式很有效,不过很少应用用于其他场景下。更多的情况下回使用setState,它仅仅会把传入的对象合并到已有的state对象。

例如:

getInitialStatefunciton(){
      return {

dropZoneEntered:false,

title:'Fantastic Survey',

introduction:'This survey isfantastic!',

question :[]

 

};

}

这时,调用this.setState({title:"Fantasticsurvey 2.0"})仅仅影响this.setState.title的值,而this.state.dropZoneEnteredthis.state.introductionthis.state.questions不会受影响。

而如果调用this.replaceState({title:"FantasticSurvey 2.0"}),则会用新的对象{title:“Fantastic Survey 2.0}替换掉整个state对象,同时把this.state.dropZone-Entered]this.state.introductionthis.state.questions全部清除掉。这样做很可能中断render函数执行,因为它期望this.state.questions是一个数组而不是undefined。现在使用this.setState可以实现上文中提到事件处理器方法。

使用this.State可以实现上文提到的事件处理器方法。

handleFormChange:function(formData){

this.setSate(formData);

}.

handleDragOver:function(ev){

//这保证handleDroZoneDrop可以被调用

ev.preventDefault();

},

handleDragEnter:function(){

this.setState({dropZoneEntered:true});

},

handleDragLeave:function(){

this.setState({dropZoneEntered:false});

},

handleDrop:function(ev){

var questionType =ev.dataTransfer.getData('questionType');

var questions =this.state.questions;

questions = questions.concat({type:questionType});

this.setState({

questions:questions,

dropZoneEntered:false

});

});

 这一点很重要永远不要尝试通过setState或者replaceState以外的方法去修改state对象,类似this.state.saveInProgress =true通常不是一个好主意,因为它无法通知React师傅需要重新渲染组件,而且可能回答熬制下次调用setState时出现意外结果。

 

五、事件对象

很多事件处理器只要触发就会完成功能,但有时也会需要关于用户输入的更多信息。例如:

var AnswerEssayQuestion=React.createClass({

handleComplete:functin(event){

this.callMethodOnProps('onCompleted',event.target.value);

},

},

render:function(){
           return(

<div className="form-group">

<lavel className="survey-item-label">{this.props.label}</label>

<div className="survey-item-content">

<textarea className="form-control" rows="3"onBlur={this.handleComplete}/>

</div>

</div>

);

}

通常会有一个事件对象传入到React的事件处理函数中,类似于原生的JavaScript事件监听器的写法。这里的handleComplete方法会接受一个事件对象,并通过存取event.target.value值为textarea赋值,在事件处理器中,使用event.target.value获取表单中input值是一个常规的方法,尤其在onClange事件处理器中。

注意:callMethodOnProps是由一个叫做PropsMethodMixinmixin提供的,此外这个mixin还提供了一些处理父组件之间通信的简便办法。

 

React把原生的事件封装在一个SyntheticEvent实例中,而不是直接把原生的浏览器事件传给处理器,SyntheticEvent在表现和功能上都与浏览器的原生事件一致,而且消除了跨浏览器差异。

对于用户界面而言,展示只占整体设计因素的一半,另一半则是相应用户输入,即通过JavaScript处理用户产生的事件。

React通过将事件处理器绑定到组建上处理事件,事件触发的同时更新组建的内部状态,内部状态更新会触发组件的重绘。因此,如果视图层想要渲染出事件出发后的结果,它所要做的就是渲染函数中读取组件的内部状态。

一、绑定事件处理器

React处理事件本身和原生的JavaScript事件一样:MouseEvents事件用于点击处理器,Change事件用于表单元素变化,等等,所有事件在命名上与原生的JavaScript规范一致,并且会在相同的情境下被触发,React绑定事件处理器的语法和HTML语法非常相似。比如,在我们的问卷制作工具实例中,包含了下面的代码,在Save按钮上绑定onclick事件处理器。

<button className ='btn btn-save'onClick={this.handleSaveClicked}>Save</button>

 

用户点击这个按钮时,组件的handleSaveClicked方法会被调用。这个方法中包含处理Save行为的逻辑。

 

PS:这个代码可在写法上类似普通不推荐的HTML内联事件处理器属性,比如:onClick,但其实在底层实习那上冰没有使用HTMLonClick属性。React只是用这种写法绑定事件处理器,但内部则是按照需要高效的维护着时间处理器。

如果不用JSX语法,你可以选择在参数对象的属性上指定事件处理器,比如:

React.DOM.button({ClassName:'btnbtn-save',onClick:this.handleSaveClicked},"Save");

其中大部分事件不需要而外的处理就可以工作,但是触控事件需要通过调用一下代码手动启动:

React.initializeTouchEventtrue);

 

二、事件和状态

1、设想你需要让一个组件随着用户的输入而改变,比如在问卷编辑器中,你想要让用户从一个问题类型的菜单当中拖拽问卷问题。

首先,在渲染函数内部基于HTML5拖放(Drag and DropAPI注册事件处理器,代码如下:

var SurveyEdit =React.creatclass{
 

renderfunction(){
     <div className='survey-edit'>

<div className='row'>

<aside className='sidebar col-md-3'>

<h2>Module</h2>

<DraggableQuestions>

</aside>

<div className='survey-canvas col-md-9'>

    <div

className ={'drop-zone well well-drop-zone'}

onDragOver={this.handleDragOver}

onDragEnter={this.handleDragEnter}

onDragLeave={this.handleDragLeave}

onDrop ={this.handleDrop}

>

Drag and drop a module from the left

</div>

 

</div>

 

</div>

    </div>

}

});

 

三、根据状态进行渲染

事件处理器方法还需要完成一件事——展开当前已经加入的题目清单。为了实现该功能,你需要充分利用每个React组件的内部状态,组件默认是null,但是可以通过它的getInitialState方法将其出事话为合理的值,比如:

getInitaSatefunciton (){

return  {

dropZoneEntered:false

title:’‘,

introduction' ',

quesions:【】

}

}

以上代码组件初始化了默认值:一个空标题、一个空的介绍、一组空的题目以及一个值为falsedropZoeEntered属性,用于表示当前用户没有拖拽任何内容那个到放置区域。

到这里,你已经可以在render方法当中读取this.state,以便向用户展示当前表单中所有数据了。

 

四、更新状态

更新组件内部状态会出发组件重绘,所以接下来要做的事情就是在拖拽的事件处理器方法中更新状态,然后再次运行render函数,它会从this.state中读取新数据来显示标题,介绍及题目,用户会看到所有内容被正确的更新。

更新组件状态有两种方案:组件的setState方法和repaceState方法。replaceState用一个全新的state对象完整的替换掉原有的state。使用不可变数据结构表示状态时,这种方式很有效,不过很少应用用于其他场景下。更多的情况下回使用setState,它仅仅会把传入的对象合并到已有的state对象。

例如:

getInitialStatefunciton(){
      return {

dropZoneEntered:false,

title:'Fantastic Survey',

introduction:'This survey isfantastic!',

question :[]

 

};

}

这时,调用this.setState({title:"Fantasticsurvey 2.0"})仅仅影响this.setState.title的值,而this.state.dropZoneEnteredthis.state.introductionthis.state.questions不会受影响。

而如果调用this.replaceState({title:"FantasticSurvey 2.0"}),则会用新的对象{title:“Fantastic Survey 2.0}替换掉整个state对象,同时把this.state.dropZone-Entered]this.state.introductionthis.state.questions全部清除掉。这样做很可能中断render函数执行,因为它期望this.state.questions是一个数组而不是undefined。现在使用this.setState可以实现上文中提到事件处理器方法。

使用this.State可以实现上文提到的事件处理器方法。

handleFormChange:function(formData){

this.setSate(formData);

}.

handleDragOver:function(ev){

//这保证handleDroZoneDrop可以被调用

ev.preventDefault();

},

handleDragEnter:function(){

this.setState({dropZoneEntered:true});

},

handleDragLeave:function(){

this.setState({dropZoneEntered:false});

},

handleDrop:function(ev){

var questionType =ev.dataTransfer.getData('questionType');

var questions =this.state.questions;

questions = questions.concat({type:questionType});

this.setState({

questions:questions,

dropZoneEntered:false

});

});

 这一点很重要永远不要尝试通过setState或者replaceState以外的方法去修改state对象,类似this.state.saveInProgress =true通常不是一个好主意,因为它无法通知React师傅需要重新渲染组件,而且可能回答熬制下次调用setState时出现意外结果。

 

五、事件对象

很多事件处理器只要触发就会完成功能,但有时也会需要关于用户输入的更多信息。例如:

var AnswerEssayQuestion=React.createClass({

handleComplete:functin(event){

this.callMethodOnProps('onCompleted',event.target.value);

},

},

render:function(){
           return(

<div className="form-group">

<lavel className="survey-item-label">{this.props.label}</label>

<div className="survey-item-content">

<textarea className="form-control" rows="3"onBlur={this.handleComplete}/>

</div>

</div>

);

}

通常会有一个事件对象传入到React的事件处理函数中,类似于原生的JavaScript事件监听器的写法。这里的handleComplete方法会接受一个事件对象,并通过存取event.target.value值为textarea赋值,在事件处理器中,使用event.target.value获取表单中input值是一个常规的方法,尤其在onClange事件处理器中。

注意:callMethodOnProps是由一个叫做PropsMethodMixinmixin提供的,此外这个mixin还提供了一些处理父组件之间通信的简便办法。

 

React把原生的事件封装在一个SyntheticEvent实例中,而不是直接把原生的浏览器事件传给处理器,SyntheticEvent在表现和功能上都与浏览器的原生事件一致,而且消除了跨浏览器差异。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

React-事件处理详解 的相关文章

  • 函数式组件与类组件有何不同?

    与React类组件相比 React函数式组件究竟有何不同 在过去一段时间里 典型的回答是类组件提供了更多的特性 比如state 当有了Hooks后 答案就不再是这样了 或许你曾听过它们中的某一个在性能上的表现优于另一个 那是哪一个 很多此类
  • Java中创建事件监听器的五种方法

    在Java中处理事件的办法最原始的方法如下 一 使用内部类 一个个设置Button然后创建一个内部类 用ActionPerformed来实现按钮事件内容 import javax swing import java awt import j
  • React重点知识拓展,含Hooks、路由懒加载等

    第7章 React扩展 一 setState 1 setState更新状态的2种写法 setState stateChange callback 对象式的setState stateChange为状态改变的对象 该对象可以体现出状态的更改
  • kafka常用命令

    启动zookeeper bin zookeeper server start sh config zookeeper properties 启动kafka bin kafka server start sh config server pr
  • 在react项目中,使用craco插件进行mobx配置解决方案

    在使用react项目中 不可避免的要使用蚂蚁金服出品的ant desgin前端UI组件 ant desgin推荐使用 craco 一个对 create react app 进行自定义配置的社区解决方案 对 create react app
  • React Router 路由守卫

    React Router 路由守卫 组件内路由守卫 1 下面是使用高阶组件实现路由守卫的示例代码 import React from react import Route Redirect from react router dom con
  • React学习之扩展浅比较(三十四)

    注意 这玩意也已经被React PureComponent的功能取代了 这里依旧是提一下 主要是React v15的版本中的react with addons js 这些玩意还存在 哎 害人呐 引入 import shallowCompar
  • 在校学生如何白嫖黑群辉虚拟机和内网穿透,实现海量资源的公网访问?(小白专用)

    文章目录 前言 本教程解决的问题是 按照本教程方法操作后 达到的效果是 前排提醒 1 搭建群辉虚拟机 1 1 下载黑群辉文件 vmvare虚拟机安装包 1 2 安装VMware虚拟机 1 3 解压黑 群辉虚拟机文件 1 4 虚拟机初始化 1
  • vue 全局组件注册_如何注册vue3全局组件

    vue 全局组件注册 With the new versions of Vue3 out now it s useful to start learning how the new updates will change the way w
  • 如何在 Ubuntu 20.04 上使用 React 前端设置 Ruby on Rails v7 项目

    作者选择了电子前沿基金会接受捐赠作为为捐款而写程序 介绍 红宝石 on Rails是一个流行的服务器端 Web 应用程序框架 它为当今网络上存在的许多流行应用程序提供支持 例如GitHub Basecamp 声云 Airbnb and Tw
  • 配置使用Eslint的时候 版本错误 "eslint": "5.6.0" a different version of eslint was detected higher up in the tr

    1 如果你也遇到下面的问题 你可以 按照命令行提示的那样 下面这四步完成的一般就可以了 但是不排除你在运行的时候忘记下载某些依赖 1 删除 package lock json 不是package json 你可以选择 yarn lock 或
  • chrome浏览器安装redux-devtools调试工具

    chrome浏览器安装redux devtools调试工具 1 点击进入https www chromefor com 2 在搜索框搜索redux 3 找到最新版本 Redux DevTools v2 17 0 进行下载 4 选择下载线路
  • 一文揭秘饿了么跨端技术的演进、实践与落地

    本文会先带领大家一起简单回顾下跨端技术背景与演进历程与在这一波儿接着一波儿的跨端浪潮中的饿了么跨端现状 以及在这个背景下 相较于业界基于 React Vue 研发习惯出发的各种跨端方案 饿了么为什么会选择走另外一条路 这个过程中我们的一些思
  • React官方文档--Lifting State Up

    Lifting State Up 如果 几个组件需要同时影响并且修改同一个数据 我们建议将这个共享状态进行提升 给他们最近的共同祖先 在这个部分 我们将要创建一个温度计算器来判断水会不会在给定温度下沸腾 我们将从一个叫做BoilingVer
  • 【react】回调函数形式的ref

    回调函数有3个特点 是我定义的函数 我没有调用这个函数 在我没有调用的情况下这个函数自己执行了 ref绑定一个箭头函数作为回调函数 可以输出以下这段看下 ref绑定的箭头函数是会自己执行的 class Demo extends React
  • hooks实践总结

    何为hooks 在React中hook是指不编写 class 的情况下使用 state 以及其他的 React 特性 而Vue3也推出了具有相同功能的组合式API 如果你用过Vue3就会知道在 setup 中你应该避免使用 this 因为h
  • 【React】 4课 react初识组件

    首先我们如1课创建一个文件夹在文件夹中安装react环境需要的配置文件 npm init y npm i babel standalone D npm i react react dom D 安装配置文件教程链接 https blog cs
  • vue发展历史简介

    基本介绍 Vue 是一套用于构建用户界面的 渐进式框架 与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用 最初它不过是个人项目 时至今日 已成为全世界三大前端框架之一 github 上拥有 17 8万 Star 领先于 Reac
  • error Missing “key“ prop for element in array react/jsx-key

    react遇到一个奇怪的问题 error Missing key prop for element in array react jsx key 检查了jsx中使用map的 都定义了key div otherList map item an
  • React配置@src根路径

    第一种 直接修改node modules包中的webpack config js文件 找到node modules react scripts config webpack config js文件 修改其中alias中的配置 添加 src

随机推荐