react 项目实战(二)创建 用户添加 页面 及 fetch请求 json-server db.json -w -p 8000
1.安装 路由
npm install -S react-router@3.x
2.新增页面
我们现在的应用只有一个Hello React的页面,现在需要添加一个用于添加用户的页面。
首先在/src目录下新增一个pages目录,用于存放渲染页面的组件。
然后在/src/pages中新增一个UserAdd.js文件。
在这个文件中写入一个基本的React组件:
import React from 'react'; // 添加用户组件
class UserAdd extends React.Component {
// 渲染
render() {
return (
<div>User add page.</div>
);
}
} // 向外暴露
export default UserAdd;
3.配置路由
我们需要使用react-router提供的路由组件来控制当前路由下页面应该渲染的组件。
修改/src/index.js为:
// 配置路由
import React from 'react';
import ReactDOM from 'react-dom';
// 引入react-router
import { Router, Route, hashHistory } from 'react-router';
import UserAddPage from './pages/UserAdd' // 渲染
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/user/add" component={UserAddPage} />
</Router>
), document.getElementById('root'));
打开浏览器的http://localhost:3000发现页面一片空白,在控制台中可以看到一个错误信息:

这是因为我们只配了一个/user/add的路由,我们来访问一下http://localhost:3000/#/user/add看看

新页面出来了。现在需要把上面的那个错误干掉:新建一个主页,并在主页中添加一个链接链到添加用户的页面。
还是在/src/pages/中新建一个Home.js,写入代码:
import React from 'react';
import { Link } from 'react-router'; class Home extends React.Component {
render () {
return (
<div>
<header>
<h1>Welcome</h1>
</header> <main>
<Link to="/user/add">添加用户</Link>
</main>
</div>
);
}
} export default Home;
然后在/src/index.js中添加一个指向Home的Route:
// 配置路由
import React from 'react';
import ReactDOM from 'react-dom';
// 引入react-router
import { Router, Route, hashHistory } from 'react-router';
import HomePage from './pages/Home';
import UserAddPage from './pages/UserAdd'; // 渲染
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={HomePage} />
<Route path="/user/add" component={UserAddPage} />
</Router>
), document.getElementById('root'));

首页已经可以正常访问了,并且点击添加用户也正确地跳转到了添加用户页面。
Q: 为什么我看到的url里有一个’#’?
A: 这是由于我们给Router组件传入了hashHistory,url中’#’及’#’以后的部分属于hash,hash的变化并不会引起页面的重新刷新,而hashHistory会监听hash的变化使得Router组件能够根据url渲染出正确的组件。除了hash History之外还有browserHistory和memoryHistory。使用browserHistory可以让url变得像标准的url一样(没有#),但是需要在后端做一些特殊处理;memoryHistory是用于做服务端渲染时使用的。
Q: 为什么Home.js里要用Link组件而不是一个标准的a标签?
A: 上面说了,我们使用了hashHistory,正确的页面url中应该都是有一个’#’的,如果直接使用a标签,你需要这么写:<a href=”/#/user/add”>添加用户</a>。但是如果我们想要换成browserHistory,就需要把所有标签中的’#’去掉。使用react-router提供的Link组件可以让我们无视history之间的差异性,直接写标准的路由”/user/add”就可以了。此外,由于我们写的是单页面应用(SPA),Link组件会阻止页面的跳转(仅仅只是改变了url,然后改变了渲染的组件)。
4.编写页面
我们定义了User的结构为:
{
"id": 10000,
"name": "一韬",
"age": 25,
"gender": "male"
}
在新建的时候,我们需要使用post方式将新用户的name、age、gender发送给接口http://localhost:3000/user,因此这个添加用户的页面需要提供一个包含上述3个字段控件的表单:
src / pages / UserAdd.js
import React from 'react'; // 添加用户组件
class UserAdd extends React.Component {
// 构造器
constructor(props) {
super(props);
// 定义初始化状态
this.state = {};
} render() {
return (
<div>
<header>
<div>添加用户</div>
</header> <main>
<form>
<label>用户名:</label>
<input type="text" />
<br />
<label>年龄:</label>
<input type="number" />
<br />
<label>性别:</label>
<select>
<option value="">请选择</option>
<option value="male">男</option>
<option value="female">女</option>
</select>
<br />
<br />
<input type="submit" value="提交" />
</form>
</main>
</div>
);
}
} export default UserAdd;
现在我们的页面是这个样子:

获取表单的值
现在我们可以在表单中填写数据了,但是还不能获取到我们输入的值。
在React中处理表单有些不一样,由于React提倡“单向数据流”,React中的表单并不提供双向数据绑定的功能,我们需要给表单绑定它的value,然后提供一个onChange的处理方法来更新value的值。
这里我们使用组件的state来维护表单的值,在onChange的时候使用setState来更新值,最后,在表单提交事件被触发的时候,我们输出state来观察最终获得的表单值:
src / pages / UserAdd.js
import React from 'react'; // 添加用户组件
class UserAdd extends React.Component {
// 构造器
constructor(props) {
super(props);
// 定义初始化状态
this.state = {
name: '',
age: 0,
gender: ''
};
}
// 输入框改变事件
handleValueChange(field, value, type='string') {
// 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型
if(type === 'number'){
value = + value;
}
// 设置状态值
this.setState({
[field]: value
});
}
// 按钮提交事件
handleSubmit(e){
// 阻止表单submit事件自动跳转页面的动作
e.preventDefault();
alert(JSON.stringify(this.state));
} render() {
// 定义常量
const {name, age, gender} = this.state;
return (
<div>
<header>
<div>添加用户</div>
</header> <main>
<form onSubmit={(e) => this.handleSubmit(e)}>
<label>用户名:</label>
<input
type="text"
value={name}
onChange={(e) => this.handleValueChange('name', e.target.value)} />
<br />
<label>年龄:</label>
<input
type="number"
value={age || ''}
onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} />
<br />
<label>性别:</label>
<select
value={gender}
onChange={(e) => this.handleValueChange('gender', e.target.value)}>
<option value="">请选择</option>
<option value="male">男</option>
<option value="female">女</option>
</select>
<br />
<br />
<input type="submit" value="提交" />
</form>
</main>
</div>
);
}
} export default UserAdd;
在页面中填写表单,点提交后可以看到如下界面:

调用接口创建用户
拿到了表单数据,我们离目标已经很近了,就差最后一步:把表单的值通过接口提交
调用接口可以有很多方法:Ajax、表单提交、fetch。
由于直接使用表单提交会引起页面的跳转,这不符合我们单页应用的原则。这里我们使用比Ajax更先进易用的fetch。
修改/pages/UserAdd.js中的handleSubmit方法:
handleSubmit (e) {
e.preventDefault();
const {name, age, gender} = this.state;
fetch('http://localhost:3000/user', {
method: 'post',
// 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
body: JSON.stringify({
name,
age,
gender
}),
headers: {
'Content-Type': 'application/json'
}
})
.then((res) => res.json())
.then((res) => {
// 当添加成功时,返回的json对象中应包含一个有效的id字段
// 所以可以使用res.id来判断添加是否成功
if (res.id) {
alert('添加用户成功');
this.setState({
name: '',
age: 0,
gender: ''
});
} else {
alert('添加失败');
}
})
.catch((err) => console.error(err));
}
填写表单然后点击提交后,可以看到弹出一个添加成功的提示框:

在/server目录执行json-server db.json -w -p 8000
打开http://localhost:8000/user查看所有用户列表,发现用户已经被添加进去了:


至此就完成了基本的添加用户功能~
注:完成的代码 src / pages / UserAdd.js
import React from 'react'; // 添加用户组件
class UserAdd extends React.Component {
// 构造器
constructor(props) {
super(props);
// 定义初始化状态
this.state = {
name: '',
age: 0,
gender: ''
};
}
// 输入框改变事件
handleValueChange(field, value, type='string') {
// 由于表单的值都是字符串,我们可以根据传入type为number来手动转换value的类型为number类型
if(type === 'number'){
value = + value;
}
// 设置状态值
this.setState({
[field]: value
});
}
// 按钮提交事件
handleSubmit(e){
// 阻止表单submit事件自动跳转页面的动作
e.preventDefault();
// 定义常量
const { name, age, gender } = this.state;
// 发送请求
fetch('http://localhost:8000/user', {
method: 'post',
// 使用fetch提交的json数据需要使用JSON.stringify转换为字符串
body: JSON.stringify({
name,
age,
gender
}),
headers: {
'Content-Type': 'application/json'
}
})
// 强制回调的数据格式为json
.then((res) => res.json())
// 成功的回调
.then((res) => {
// 当添加成功时,返回的json对象中应包含一个有效的id字段
// 所以可以使用res.id来判断添加是否成功
if(res.id){
alert('添加用户成功!');
// 初始化
this.setState({
name: '',
age: 0,
gender: ''
});
}else{
alert('添加用户失败!');
}
})
// 失败的回调
.catch((err) => console.error(err));
} render() {
// 定义常量
const {name, age, gender} = this.state;
return (
<div>
<header>
<div>添加用户</div>
</header> <main>
<form onSubmit={(e) => this.handleSubmit(e)}>
<label>用户名:</label>
<input
type="text"
value={name}
onChange={(e) => this.handleValueChange('name', e.target.value)} />
<br />
<label>年龄:</label>
<input
type="number"
value={age || ''}
onChange={(e) => this.handleValueChange('age', e.target.value, 'number')} />
<br />
<label>性别:</label>
<select
value={gender}
onChange={(e) => this.handleValueChange('gender', e.target.value)}>
<option value="">请选择</option>
<option value="male">男</option>
<option value="female">女</option>
</select>
<br />
<br />
<input type="submit" value="提交" />
</form>
</main>
</div>
);
}
} export default UserAdd;
.
react 项目实战(二)创建 用户添加 页面 及 fetch请求 json-server db.json -w -p 8000的更多相关文章
- react 项目实战(七)用户编辑与删除
添加操作列 编辑与删除功能都是针对已存在的某一个用户执行的操作,所以在用户列表中需要再加一个“操作”列来展现[编辑]与[删除]这两个按钮. 修改/src/pages/UserList.js文件,添加方 ...
- 010医疗项目-模块一:用户添加的实现(Dao,Service,Action,增加页面调试,提交页面调试)
要实现的效果:
- react 项目实战(一)创建项目 及 服务端搭建
1.安装 React社区提供了众多的脚手架,这里我们使用官方推荐的create-react-app. //安装脚手架 npm install -g create-react-app //生成并运行项目 ...
- 【NFS项目实战二】NFS共享数据的时时同步推送备份
[NFS项目实战二]NFS共享数据的时时同步推送备份 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品, ...
- React项目实战:react-redux-router基本原理
React相关 React 是一个采用声明式,高效而且灵活的用来构建用户界面的框架. JSX 本质上来讲,JSX 只是为React.createElement(component, props, .. ...
- miniFTP项目实战二
项目简介: 在Linux环境下用C语言开发的Vsftpd的简化版本,拥有部分Vsftpd功能和相同的FTP协议,系统的主要架构采用多进程模型,每当有一个新的客户连接到达,主进程就会派生出一个ftp服务 ...
- react 项目实战(六)提取布局组件
重复代码是混乱的根源!,本篇文章我们来继续消灭重复代码. 目标 细心的同学应该能发现:每一个Page组件(/src/pages下的组件)的render方法都拥有相似的jsx结构,比如: render ...
- Asp.Net Core 2.0 项目实战(8)Core下缓存操作、序列化操作、JSON操作等Helper集合类
本文目录 1. 前沿 2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装 3.XmlHelper快速操作xml文档 4.Serializatio ...
- react 项目实战(五)渲染用户列表
现在我们需要一个页面来展现数据库中记录的用户. 在/src/pages下新建UserList.js文件. 创建并导出UserList组件: import React from 'react'; cla ...
随机推荐
- 迅为iTOP-4418/6818开发板MiniLinux下的GPS使用手册
平台:iTOP-4418/6818开发板 系统:MiniLinux 在 Mini Linux 系统环境下 iTOP-4418 和 6818 的 GPS 实验调试步骤.给用户提供了“iTOP-4418- ...
- bat运行当前路径下程序
批处理中获取当前路径的方法可能有好几种,具体有几种我没有研究过,本文只是对其中的两种之间的差别进行简单说明 本文涉及的两个当前路径标示为:%cd%.%~dp0 注:我的系统是win7旗舰版,其它系统没 ...
- 获取minist数据并转换成lmdb
caffe本身是没有数据集的,但在data目录下有获取数据的一些脚本.MNIST,一个经典的手写数字库,包含60000个训练样本和10000个测试样本,每个样本为28*28大小的黑白图片,手写数字为0 ...
- vue hash模式和404页面的配置
1.设置我们的路由配置文件(/src/router/index.js): { path:'*', component:Error } 这里的path:’*’就是找不到页面时的配置,component是 ...
- MFC模拟鼠标点击
MFC 工程 把以下代码放到你想要响应的函数里面就行 CPoint pt; GetCursorPos(&pt);//获取鼠标在屏幕的当前位置 SetCursorPos(100,200);//移 ...
- 「 Luogu P1122 」 最大子树和
# 题目大意 真讨厌题面写的老长老长的. 这个题的意思就是给定一棵无根树,每个节点都有一个美丽值(可能是负数),可以删掉一些边来删除某些点,现在要求你求出可以删掉任意条边的情况下,这个树上的剩余节点的 ...
- HDU - 2612 Find a way(BFS搜索)
题目: 链接 思路: 用BFS分别以‘Y’和‘M’的位置为起点进行两次搜索,并把这两次的搜索结果在一个二维数组中保存下来,在对地图遍历遇到‘@’更行最小值. PS: 如果用‘Y’和‘M’点分别去搜每个 ...
- [Python3网络爬虫开发实战] 2.2-网页基础
用浏览器访问网站时,页面各不相同,你有没有想过它为何会呈现这个样子呢?本节中,我们就来了解一下网页的基本组成.结构和节点等内容. 1. 网页的组成 网页可以分为三大部分——HTML.CSS和JavaS ...
- [Python3网络爬虫开发实战] 1.8.2-Scrapy的安装
Scrapy是一个十分强大的爬虫框架,依赖的库比较多,至少需要依赖的库有Twisted 14.0.lxml 3.4和pyOpenSSL 0.14.在不同的平台环境下,它所依赖的库也各不相同,所以在安装 ...
- Yum:更换aliyun的yum源
备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup centos7 wget -O /et ...