为什么80%的码农都做不了架构师?>>>   

本文记录了在官网学习如何使用JSX+ES6开发React的过程。 。

全文共分为3篇内容:

  1. JSX语法与React组件
  2. 状态、事件与动态渲染
  3. 列表、键值与表单

扩展:webpack搭建React开发环境

列表与组件的键值

首先让我们看看在JavaScript中我们是如何处理一个列表的:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

例子中使用map方法将每个元素的值*2,最后得到的数组为:[2, 4, 6, 8, 10]。在React中,处理组件数组的方式与之类似。

渲染多个组件

下面的例子,我们使用map()方法来创建组件中的一系列元素:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =><li>{number}</li>
);

listItem就是一个包含多个<li>标签的组件。然后我们将listItem用<ul>标签包裹起来并在浏览器呈现:

ReactDOM.render(<ul>{listItems}</ul>,document.getElementById('root')
);

测试代码

通过类似的方法,我们可以使用数组来创建一系列元素。

基于列表的组件

大部分情况,我们希望在一个组件中完成一个列表元素的渲染。将前面的例子稍加修改:

//构建组件
function NumberList(props) {const numbers = props.numbers;//根据输入的参数获取一个<li>标签的列表const listItems = numbers.map((number) =><li>{number}</li>);//用<ul>包裹<li>并返回return (<ul>{listItems}</ul>);
}
//设置输入参数
const numbers = [1, 2, 3, 4, 5];
//渲染组件
ReactDOM.render(<NumberList numbers={numbers} />,document.getElementById('root')
);

当我们执行这个例子的代码时,会发现在浏览器中输出一个警告:" a key should be provided for list items"。"键值(Key)"在创建列表元素时是一个附加的属性,下一节会详细说明使用它的原因。

通过number.map()方法向组建中的元素增加键值:

function NumberList(props) {const numbers = props.numbers;const listItems = numbers.map((number) =>//根据number输出设置li的key<li key={number.toString()}>{number}</li>);return (<ul>{listItems}</ul>);
}const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(<NumberList numbers={numbers} />,document.getElementById('root')
);

测试代码

键值的使用

在React中,键值(keys)用来标记那些元素被修改了。在使用数组时,应该给数组元素标记键值以便于批量更新的效率:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =><li key={number.toString()}>{number}</li>
);

最好使用一个字符串来表示key值,并且确保兄弟节点之间的唯一性。例如使用业务id作为键值:

const todoItems = todos.map((todo) =><li key={todo.id}>{todo.text}</li>
);

在某些情况下无法获取到合理的id值,可以直接使用列表索引:

const todoItems = todos.map((todo, index) =><li key={index}>{todo.text}</li>
);

如果列表中的元素可以重新排序,建议不要使用索引作为键值,这样会导致渲染缓慢。如果你对键值(keys)的使用有浓厚的兴趣,参看:in-depth explanation about why keys are necessary。

使用键值扩展组件

键值仅仅在最外层列表中存在意义。例如,如果想抽取出一个名为ListItem的组件,最好在<ListItem />上标记key值,而不是组件中的<li>元素上。

下面是一些错误使用键值的例子:

function ListItem(props) {const value = props.value;//不应该在这里使用键值return (<li key={value.toString()}>{value}</li>);
}function NumberList(props) {const numbers = props.numbers;/**建议在这里使用并标记键值*/const listItems = numbers.map((number) =><ListItem value={number} />);return (<ul>{listItems}</ul>);
}const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(<NumberList numbers={numbers} />,document.getElementById('root')
);

正确使用键值的例子:

function ListItem(props) {return <li>{props.value}</li>;
}function NumberList(props) {const numbers = props.numbers;const listItems = numbers.map((number) =><ListItem key={number.toString()}value={number} />);return (<ul>{listItems}</ul>);
}const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(<NumberList numbers={numbers} />,document.getElementById('root')
);

键值需要与兄弟节点保证唯一

在使用的过程中,键值只要保证和兄弟节点的键值没有碰撞即可,并不需要全局唯一。在不同的列表中我们可以使用相同的key:

function Blog(props) {const sidebar = (<ul>{props.posts.map((post) =><li key={post.id}>{post.title}</li>)}</ul>);const content = props.posts.map((post) =><div key={post.id}><h3>{post.title}</h3><p>{post.content}</p></div>);return (<div>{sidebar}<hr />{content}</div>);
}const posts = [{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},{id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(<Blog posts={posts} />,document.getElementById('root')
);

测试代码

在上面的例子中sidebar、content是两个不同的队列,但是使用了相同的key值。

键值虽然显示的设置到元素或组件上,但是并不能在组件内部直接获取,如果需要使用键值,我们需要另外设置:

const content = posts.map((post) =><Postkey={post.id}id={post.id}title={post.title} />
);

这样,在Post组件中可以通过this.props.id获取到id值,而this.props.key获取不到任何值。

将map()方法嵌入到JSX中

在下面的例子中,我们直接在map()方法中生成ListItem:

function NumberList(props) {const numbers = props.numbers;const listItems = numbers.map((number) =><ListItem key={number.toString()}value={number} />);return (<ul>{listItems}</ul>);
}

JSX允许在大括号"{}"中嵌入任何表达式,因此我们可以直接嵌入map()方法使用:

function NumberList(props) {const numbers = props.numbers;return (<ul>{numbers.map((number) =><ListItem key={number.toString()}value={number} />)}</ul>);
}

测试代码

表单

因为表单元素都保持着一些内部状态,所以HTML的表单与React的表单工作方式有一些区别。例如在标准的HTML表单只接收单个名称:

<form><label>Name:<input type="text" name="name" /></label><input type="submit" value="Submit" />
</form>

在用户提交表单时,浏览器默认会跳转到新的页面,当然在默认情况下React中的表单也是这样工作的。但是在大多数情况下,在用户提交数据到后台之前需要使用JavaScript来验证某些数据的合法性。实现这一点的方法我们称之为“controlled components(受控组件)”。

受控组件

在HTML中,<input><textarea>, and <select> 这些表单元素都包含自己的状态,并在用户输入时发生改变。而在React中,可变的状态通常保存在state属性值中,并且只能通过setState来改变。

我们使用“受控组件”将2者合并,负责渲染表单的React组件还需要控制用户在渲染完毕后的各种输入操作。看下面这个例子:

class NameForm extends React.Component {constructor(props) {super(props);this.state = {value: ''};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('A name was submitted: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>Name:<input type="text" value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="Submit" /></form>);}
}

测试代码

例子中通过在onChange中注册this.handleChange方法来记录值的改变,在改变时会通过setState()设置this.state值,并使用render渲染。此外,组件还用this.handleSubmit来拦截提交事件。这个例子中的组件称之为"受控组件"。

在受控组件中,每一个状态值的改变都会有一个相关处理函数来处理,这样可以直接修改或验证用户的输入。例如下面这个例子,我们将所有的输入强行变成大写:

handleChange(event) {this.setState({value: event.target.value.toUpperCase()});
}

textarea标签

在HTML中,<textarea>由其子元素来定义文本:

<textarea>Hello there, this is some text in a text area
</textarea>

在React中,<textarea>使用一个value属性来代替子元素。这样使用<textarea>标签与使用单行输入元素(<input type="text">)类似:

class EssayForm extends React.Component {constructor(props) {super(props);this.state = {value: 'Please write an essay about your favorite DOM element.'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('An essay was submitted: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>Name:<textarea value={this.state.value} onChange={this.handleChange} /></label><input type="submit" value="Submit" /></form>);}
}

在这里例子中,在构造函数就初始化了this.state.value。因此<textarea>会显示一个初始值。

select标签

在HTML中,select会创建一个下拉菜单,例如:

<select><option value="grapefruit">Grapefruit</option><option value="lime">Lime</option><option selected value="coconut">Coconut</option><option value="mango">Mango</option>
</select>

由于"cocount"设置了selected属性,所以默认状态下这个<option>是被选中的。在React中,<select>元素使用value元素来设定这个默认值,这在受控组件中使用更方便,因为只需要在一个地方更新它:

class FlavorForm extends React.Component {constructor(props) {super(props);this.state = {value: 'coconut'};this.handleChange = this.handleChange.bind(this);this.handleSubmit = this.handleSubmit.bind(this);}handleChange(event) {this.setState({value: event.target.value});}handleSubmit(event) {alert('Your favorite flavor is: ' + this.state.value);event.preventDefault();}render() {return (<form onSubmit={this.handleSubmit}><label>Pick your favorite La Croix flavor:<select value={this.state.value} onChange={this.handleChange}><option value="grapefruit">Grapefruit</option><option value="lime">Lime</option><option value="coconut">Coconut</option><option value="mango">Mango</option></select></label><input type="submit" value="Submit" /></form>);}
}

测试代码

受控组件的替代方案

在某些情况下使用受控组件会非常的繁琐,因为它针对所有的变更都需要编写一个处理器来管理对应的状态。React官网推荐使用"非受控组件"技术来解决这个问题—— uncontrolled components,它是用于实现输入表单的替代技术。

原文地址:https://www.chkui.com/article/react/react_list_key_and_form

转载于:https://my.oschina.net/chkui/blog/796466

React学习(3)——列表、键值与表单相关推荐

  1. 前端学习第一周-计算机基础,html标签的介绍,其中包括列表,表格以及表单的使用

    前端学习第一周-HTML基础 文章目录 前端学习第一周-HTML基础 前言 DAY 1 计算机组成 计算机网络 DAY 2 vscode快捷方式 HTML骨架 DAY 3 HTML属性 HTML标签 ...

  2. ORA-01779: 无法修改与非键值保存表对应的列

    问题描述 错误报告 - SQL 错误: ORA-01779: 无法修改与非键值保存表对应的列 01779. 00000 -  "cannot modify a column which ma ...

  3. html 表单自动数值,web前端学习技术之对HTML5 智能表单的理解

    原标题:web前端学习技术之对HTML5 智能表单的理解 Html5新增input的form属性,用于指向特定form表单的id,实现input无需放在form标签之中,即可通过表单进行提交. - t ...

  4. HTML学习笔记(五)_HTML5表单相关元素和属性

    1. HTML表单元素:        <form../>元素用于生成输入表单,该元素不会生成可视化部分,在HTML5之前,其他表单控件,如单行文本框.多行文本域.单选按钮.复选框等必须放 ...

  5. JavaScript学习(六十八)—表单校验案例

    JavaScript学习(六十八)-表单校验案例 学习内容 (一).如何获取页面的元素-利用id获取 格式:var 变量名称 =document.getElementById('要获取的元素的id的值 ...

  6. html中的列表、表格、表单

    目录 一.列表(有序列表和无序列表) 1.无序列表 2.有序列表 3.列表的嵌套 二.表格 1.表格所需的主要标签 2.详细介绍表格的制作 3.单元格的合并(跨行和跨列) ​ 三.表单 1.表单标签 ...

  7. Web前端——HTML中的列表、表格、表单

    一. 列表 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF- ...

  8. HTML列表、表格、表单

    HTML 表格 Previous Page Next Page 你可以使用 HTML 创建表格. 实例 表格 这个例子演示如何在 HTML 文档中创建表格. 表格边框 本例演示各种类型的表格边框. ( ...

  9. 前端之HTML列表、表格及表单

    文章目录 1.表格 table 1.1.创建表格 1.2.表格属性 1.3.表头单元格标签th 1.4.表格标题caption 1.5.合并单元格 1.5.1.合并单元格2种方式 1.5.2.合并单元 ...

最新文章

  1. Python之Pandas库学习(一):简介
  2. 从ASP.NET传递参数给水晶报表
  3. 安徽工业大学计算机考研调剂,安徽工业大学2019年考研预调剂公告
  4. c++ 纯虚成员函数+抽象基类
  5. Oracle Proc开发之Makefile的编写模板
  6. nancy框架安装并使用
  7. Linux环境下的Popush部署——张凯
  8. java语言factory_一个简单例子解释 Java factory
  9. 要继续看Python写算法的内容请到那里去
  10. Thingsboard 3.1.0 - 源码编译
  11. 详解相机的sensor工作原理
  12. 九连环解法和小程序。
  13. java群发邮件_JAVA邮件群发 - Java-Android-jwebee - BlogJava
  14. python读取excel汉字转成拼音_python 批量将中文名转换为拼音
  15. 程序员正确打开碎片时间的方法
  16. 算法定义及其主要特征
  17. 用electron做一个浏览器
  18. 图像滤波【一】:从高斯滤波到引导滤波
  19. 安装SQL server需要重启计算机,SQLServer2008安装提示需要重启计算机,但是重启还是不通过解决...
  20. JavaMail怎样获取收件箱,发件箱,垃圾箱等等的全名

热门文章

  1. swift_038(Swift之guard关键字(守护))
  2. oracle索引大小暴增_oracle 如何预估将要创建的索引的大小
  3. textview 背景变形_西安昆明池桁架舞台背景搭建欢迎致电
  4. 展开被 SpringBoot 玩的日子 《 二 》 WEB 开发
  5. MySQL中字段字符集不同导致索引不能命中
  6. Promise对象和async函数
  7. bzoj 2457 [BeiJing2011]双端队列 模拟+贪心
  8. 回调函数在replace方法中的应用
  9. 程序运行时,内存占用查看
  10. Windows下svn客户端和服务器的安装使用