本文主要是介绍玩转Reactjs第五篇-基础知识(事件条件列表表单),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、前言
其实在前面介绍组件的时候,已经用到了这些知识,本章节我们重点分析下,并与Vue的用法比较。
二、事件
Reactjs中事件处理方式与原生态DOM的非常类似,只不过使用JSX的语法,采用的是小驼峰的表达方式,比如onClick,onChange,我们以SearchHot.js的"下一批"功能为例,当点击按钮,更新热词。
return (<div className="d"> <div className="s">大家都在搜:<a href="#" onClick={this.changeHot} style={{marginLeft:100}}>下一批</a></div><ul className="su">{/*引用变量表达式 */}{hotList}</ul></div> )
在a标签上增加onClick响应事件,调用的方法为changeHot,下面我们对该方法定义
changeHot(){this.setState({hotItem:['电视','手机','电脑','平板']})}
在此方法中,我们调用setState更新hotItem属性。如果直接运行,将会报this为undefined的错误,我们还需要在组件初始化方法中,将该方法绑定到组件对象。
constructor(props){// 1、调用父类构造方法super(props);//2、初始化state对象this.state = {hotItem:['口罩','手套','酒精',]};//绑定thisthis.changeHot = this.changeHot.bind(this);}
除了这种bind方式,还可以将changeHot改造为箭头函数,在箭头函数中,this指向的函数的本身,而不是函数的调用者,可以参考ES6系列教程第八篇--箭头函数详解
changeHot = () =>this.setState({hotItem:['电视','手机','电脑','平板']});
我们在a标签上增加一个默认事件,href="search.json"
return (<div className="d"> <div className="s">大家都在搜:<a href="search.json" onClick={this.changeHot} style={{marginLeft:100}}>下一批</a></div><ul className="su">{/*引用变量表达式 */}{hotList}</ul></div> )
此时再次点击按钮,发现页面跳转到search.json,这是因为执行了默认事件。现在我们需要阻止默认事件或者冒泡。
changeHot(e){e.preventDefault();e.stopPropagation();this.setState({hotItem:['电视','手机','电脑','平板'] })}
再次点击时,功能正常。
事件方法中会隐形传入一个event参数,通过调用该参数的preventDefault(),stopPropagation()阻止默认事件以及冒泡。
传参是事件的基本的功能,我们看下React如何实现传参。
return (<div className="d"> <div className="s">大家都在搜:<a href="search.json" onClick={this.changeHot.bind(this,1,"ok")} style={{marginLeft:100}}>下一批</a></div><ul className="su">{/*引用变量表达式 */}{hotList}</ul></div> )
在调用的时候绑定this对象,并依次传递相关的参数(注意:事件方法已经绑定了this,可以不需要再在初始化方法中重复绑定),在changeHot中接受并处理参数。
changeHot(id,name,e){e.preventDefault();e.stopPropagation();this.setState({hotItem:['电视','手机','电脑','平板'] });console.log("id:"+id);console.log("name:"+name)}
无论传递多少参数,隐形的event参数始终处于最后的位置。
在Vue中,事件的处理使用的是v-on内置的指令,并通过事件的修饰符简化了诸如阻止默认事件,冒泡等写法。而JSX语法中没有指令的概念,其处理方式更接近原生的DOM。
三、条件
在前面章节中,我们介绍JSX仅支持三目以及&&符运算的嵌入,而不支持if...else条件语句。我们先看三目运算和&&。
在SearchBox.js中,我们用this.state.isSearch标志符控制button按钮的disabled属性,当this.state.isSearchShow为true,按钮有效,false则无效。
return(<div style={{width:300,margin:10}}><input type="text" style={{width:150}} onChange={this.handleChange}></input> <button onClick={this.onSearchClick} disabled={this.state.isSearchShow?"":"disabled"}>搜索</button></div>)
也可以改写&&运算
return(<div style={{width:300,margin:10}}><input type="text" style={{width:150}} onChange={this.handleChange}></input> <button onClick={this.onSearchClick} disabled={!this.state.isSearchShow&&"disabled"}>搜索</button></div>)
在js中,true && expression
总是会返回 expression
, 而 false && expression
总是会返回 false。
如果是多个条件组合,三目运算就无法满足了,比如不同的状态,显示button的不同背景色,此时就需要用到if...else。
render(){//定义color变量,并根据状态显示不同的颜色let color;if(this.state.color<10){color="green"}else if(this.state.color<20){color="blue"}else if(this.state.color<30){color="red"}else{color="orange"}return(<div style={{width:300,margin:10}}><input type="text" style={{width:150}} onChange={this.handleChange}></input> <button onClick={this.onSearchClick} disabled={!this.state.isSearchShow&&"disabled"} style={{backgroundColor:color}}>搜索</button></div>)}
虽然JSX中无法直接使用if...else,但可以通过在代码段中,定义color的变量并条件赋值,再在JSX中插入color变量表达式。
在Vue中使用v-if,v-else指令进行条件控制,并对控件的隐藏和显示提供了v-show,使用更方便。
四、列表
Reactjs中对于列表使用map方法进行遍历,并拼装成JSX表达式。以SearchList.js的搜索结果列表展示为例:
render(){//1、从props中获取searchListVal,封装列表const searchValList = this.state.searchListVal.map((value)=>(<li>{value}</li>));return(<div className="d"><div className="s">搜索结果:</div>{/* 引入插槽代码 */}{this.props.children}<ul className="u" ref={this.searchul}>{/* 引用对象表达式*/}{searchValList}</ul></div> )}
遍历searchListVal数组,拼装li表达式。此时我们打开控制台,会发现有如下的warning
这个告警的意思,list应增加一个key属性。
const searchValList = this.state.searchListVal.map((value)=>(<li key={value.toString()}>{value}</li>));
告警消失,那加上这个key有什么作用呢?
这要从diff算法的原理说起。diff运算时,对于同一节点下的子元素,进行遍历比较,如果不一致,则产出一个mutation。如下:
//老节点
<ul><li>first</li><li>second</li>
</ul>
//新节点
<ul><li>first</li><li>second</li><li>third</li>
</ul>
该样例中,ul的子元素li,新老节点中第一个和第二个是完全一样的,所以无需变动,仅在尾部插入第三个li元素,就可以完成节点的更新,效率很高。如果是头部插入一个li呢?
/老节点
<ul> <li>first</li><li>second</li>
</ul>
//新节点
<ul><li>third</li><li>first</li><li>second</li>
</ul>
在diff运算过程中,比较发现第一个,第二个li元素不一样(老节点的第一个为first,新节点的第一个为third),将会销毁重建,效率会非常低。效率最高的的更新操作,仅在头部插入一个third,其他节点保持不变。为了解决这个问题,引入了key。
/老节点
<ul> <li key="1">first</li><li key="2">second</li>
</ul>
//新节点
<ul><li key="3">third</li><li key="1">first</li><li key="2">second</li>
</ul>
diff运算过程中,不是直接遍历比较,而是优先查找是否有相同的key,新老节点都有key为1,2的li元素,且值没有变化,这两个节点将保持不变,最终仅在头部插入key为3的li元素,实现了高效率的更新。
所以,key需要有以下两个特点:
- key一定是在同级的兄弟节点间设置,因为非同级节点不会进行diff运算。
- key的值在兄弟节点间必须唯一,一般用id等,最好不要用列表索引(索引可能会变化)
在Vue用使用v-for进行列表渲染,其中也需要设置key,原理是一致的。
五、表单
表单标签包括select,input,textarea,checkbox,radio等,他们是最能说明双向绑定的过程,比如SearchBox.js中的搜索输入框input
handleChange(e){this.setState({searchVal:e.target.value});}
....
return(<div style={{width:300,margin:10}}><input type="text" style={{width:150}} onChange={this.handleChange} value={this.state.searchVal}></input> <button onClick={this.onSearchClick} >搜索</button></div>)
input框的每次输入,通过onChange捕捉变化事件,并响应handleChange方法,将input的当前值更新到state中的searchVal(这就是view->model过程);searchVal赋值给input的value,searchVal值的变化,又反馈到input的value(这就是model->view)。有同学会问,这这么做不是多此一举么,其实不然,在实际使用过程中,我们会在handleChange中对输入值e.target.value进行处理,比如说银行卡号,4个数字一组,做分割处理,再设置给input框输出展示。
Reactjs还提供一种操作DOM获取input的输入值的方式,即使用ref。
首先在构造函数中定义ref
constructor(props){super(props);this.state = {searchVal:"",isSearchShow:true,color:25};this.onSearchClick = this.onSearchClick.bind(this);this.handleChange = this.handleChange.bind(this); //定义refthis.input = React.createRef();}
然后设置input的ref属性
return(<div style={{width:300,margin:10}}><input type="text" style={{width:150}} onChange={this.handleChange} ref={this.input} value={this.state.searchVal}></input> <button onClick={this.onSearchClick} >搜索</button></div>)
就可以使用ref获取input的对象句柄,比如handleChange通过ref的方式获取input的值
handleChange(e){this.setState({searchVal:this.input.current.value});}
使用的时候别忘了current关键字。此时input可以通过ref进行DOM操作,称为非受控组件。虽然这种模式打破了数据驱动view的原则,但是有时候还是比较方便的,比如获取滚动条的高度。
在Vue中可有类似的做法,通过自定义的指令操控DOM节点。
六、总结
本章节介绍了Reactjs的事件,条件,列表,表单的基本用法,并与vue进行了简单的比较。
事件的隐形event参数的使用,阻止默认事件以及冒泡,传递参数。
条件的三目运算,&&符,以及if...else条件的使用
列表使用map遍历,以及key的原理。
表单的两种不同的获取对象值的方法。
这篇关于玩转Reactjs第五篇-基础知识(事件条件列表表单)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!