React-事件处理详解

来源:互联网 发布:删除一列数据的sql语句 编辑:程序博客网 时间:2024/05/16 00:38

对于用户界面而言,展示只占整体设计因素的一半,另一半则是相应用户输入,即通过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在表现和功能上都与浏览器的原生事件一致,而且消除了跨浏览器差异。

2 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 中关村买电脑被骗了怎么办 在闲鱼被买家骗了东西怎么办 在手机店买手机被骗怎么办 买手机分期付款被骗了怎么办 买电脑被骗了怎么办啊 小米卡puk锁了怎么办 红米3x电池松动怎么办 实体店买到苹果翻新机怎么办 小米手环2米粒掉怎么办 小米字体下架了怎么办 京东白条被锁定怎么办 苹果6splus很卡怎么办 苹果6s卡槽坏了怎么办 在京东买的电脑没发票怎么办 京东上买的空调没发票怎么办 分期手机被坑了怎么办 京东退货发票丢了怎么办 买东西的发票丢了怎么办 淘宝买东西发票丢了怎么办 网上买的手机没有发票怎么办 网上买的手机没发票怎么办 手机店花呗分期额度不够怎么办 买了手机没有开票怎么办 在京东上买苹果手机没有发票怎么办 买到苹果演示机怎么办 京东白条借不了怎么办 买了东西不给退怎么办 邮政储蓄银行买东西多扣钱了怎么办 快递送错地方了怎么办 菜鸟驿站超过5天怎么办 消费者买到不合格产品怎么办 如果买到不合格的产品怎么办 买到不合格的种子怎么办 买到不合格的空调怎么办 买到不合格的家具怎么办 灭火器买到不合格产品怎么办 路边买到假手机怎么办 网上买的手机屏幕碎了怎么办 天猫订单删除了怎么办 华为入职预约满怎么办 三星c5玩王者荣耀卡怎么办