玩转Reactjs第五篇-基础知识(事件条件列表表单)

2024-03-20 10:18

本文主要是介绍玩转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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<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第五篇-基础知识(事件条件列表表单)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829144

相关文章

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

SpringIntegration消息路由之Router的条件路由与过滤功能

《SpringIntegration消息路由之Router的条件路由与过滤功能》本文详细介绍了Router的基础概念、条件路由实现、基于消息头的路由、动态路由与路由表、消息过滤与选择性路由以及错误处理... 目录引言一、Router基础概念二、条件路由实现三、基于消息头的路由四、动态路由与路由表五、消息过滤

Python实现自动化表单填写功能

《Python实现自动化表单填写功能》在Python中,自动化表单填写可以通过多种库和工具实现,本文将详细介绍常用的自动化表单处理工具,并对它们进行横向比较,可根据需求选择合适的工具,感兴趣的小伙伴跟... 目录1. Selenium简介适用场景示例代码优点缺点2. Playwright简介适用场景示例代码

Python中DataFrame转列表的最全指南

《Python中DataFrame转列表的最全指南》在Python数据分析中,Pandas的DataFrame是最常用的数据结构之一,本文将为你详解5种主流DataFrame转换为列表的方法,大家可以... 目录引言一、基础转换方法解析1. tolist()直接转换法2. values.tolist()矩阵

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式

python展开嵌套列表的多种方法

《python展开嵌套列表的多种方法》本文主要介绍了python展开嵌套列表的多种方法,包括for循环、列表推导式和sum函数三种方法,具有一定的参考价值,感兴趣的可以了解一下... 目录一、嵌套列表格式二、嵌套列表展开方法(一)for循环(1)for循环+append()(2)for循环+pyPhWiFd

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Python容器类型之列表/字典/元组/集合方式

《Python容器类型之列表/字典/元组/集合方式》:本文主要介绍Python容器类型之列表/字典/元组/集合方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 列表(List) - 有序可变序列1.1 基本特性1.2 核心操作1.3 应用场景2. 字典(D

Java中数组转换为列表的两种实现方式(超简单)

《Java中数组转换为列表的两种实现方式(超简单)》本文介绍了在Java中将数组转换为列表的两种常见方法使用Arrays.asList和Java8的StreamAPI,Arrays.asList方法简... 目录1. 使用Java Collections框架(Arrays.asList)1.1 示例代码1.

python中列表list切分的实现

《python中列表list切分的实现》列表是Python中最常用的数据结构之一,经常需要对列表进行切分操作,本文主要介绍了python中列表list切分的实现,文中通过示例代码介绍的非常详细,对大家... 目录一、列表切片的基本用法1.1 基本切片操作1.2 切片的负索引1.3 切片的省略二、列表切分的高