React-Router 中文简明教程(上)
概述
说起 前端路由,如果你用过前端 MV* 框架构建 SPA 应用(单页面应用),对此一定不陌生。
传统开发中的 路由,是由服务端根据不同的用户请求地址 URL,返回不同内容的页面,而前端路由则将这些任务通过 JS 在浏览器端完成,SPA 应用 则是前端路由的最佳适用场景,因为它结构简单,只需更新页面部分显示内容 也不必每次都从服务端获取内容。
react-router 是官方指定和维护的 React 路由库,它通过管理 URL,实现组件间切换,和状态 (state) 的变化。
准备工作
官方示例教程 react-router-tutorial 写的贴心又详细,一共14节,本文内容以官方教程为准,分成三章:
在学习前,需要你对 React 的 JSX 语法有初步的认识,如果了解 ES6 语法更好,后续的 React 系列教程我都会用 ES6 来写。建议初学者跟着教程 码一遍代码~ 为了照顾初学者,我写的可能会啰嗦些,大神勿喷~
首先你需要安装 Node.js 和 npm 包管理工具,命令行工具推荐 Git。浏览器不能直接解析 JSX 和 ES6 语法,所以需要一个编译打包工具 这里选择 webpack,全局安装 webpack —— 命令行输入:
npm install webpack -g
创建项目目录:react-router-tutorial,
接着分别创建:文件夹module,index.html,index.js(入口文件),
package.json(定义了项目所需的各个模块,和配置信息)
webpack.config.js(webpack 配置文件),目录结构如下:
index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>My First React Router App</title>
</head>
<body>
<div id=app></div>
<!-- 编译后的js文件 -->
<script src="bundle.js"></script>
</body>
</html>
package.json:
其中 npm start 为 Node.js 启动模块的默认命令,这里用 webpack-dev-server 来运行一个小型 Node.js Express 服务器,它会实时将代码编译打包在内存中(注意:这个过程并不会在你的项目文件夹里 产生任何文件)
启动项目时,只需在命令行输入npm start,访问http://localhost:8080/index.html即可浏览结果。
{
"name": "tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --inline --hot --content-base ."
},
"author": "",
"license": "ISC",
"dependencies": {
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-router": "^2.0.0"
},
"devDependencies": {
"babel-core": "^6.5.1",
"babel-loader": "^6.2.2",
"babel-preset-es2015": "^6.5.0",
"babel-preset-react": "^6.5.0",
"http-server": "^0.8.5",
"webpack": "^1.12.13",
"webpack-dev-server": "^1.14.1"
}
}
webpack.config.js:
module.exports = {
// 入口文件
entry: './index.js', // 输出文件
output: {
filename: 'bundle.js',
publicPath: ''
}, module: {
loaders: [
// 匹配到js或jsx文件后 使用 babel-loader 来处理
// '?'后面是该loader的参数设置(使用了es6和react转码器)
{
test: /\.js[x]?$/,
exclude: /node_modules/,
loader: 'babel-loader?presets[]=es2015&presets[]=react'
}
]
}
};
现在来 安装package.json中所有的 依赖模块,命令行输入:
npm install
上个厕所或喝杯咖啡 一会就好了,如果你还感觉安装过程慢,也可以换成淘宝镜像的安装方式(先安装镜像命令):
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install
一. 启动应用
创建modules/App.js
App.js:
import React from 'react'; // 定义App组件
export default class App extends React.Component {
constructor(props) {
super(props);
} render() {
return (
<h1>React Router Tutorial</h1>
);
}
}
使用 ES6 的import语句代替之前的require()方法来导入模块,使用class来创建”类”(js中根本不存在类,class只是语法糖)extends用来继承React.Component,constructor(){}为构造函数方法,export default定义了模块对外的接口 也就是”类”App,这里定义了一个叫 APP 的根组件
如果你对 ES6 的写法感到困惑,可以看下这篇文章:如何将 react 中的 ES5 写法转化成 ES6
在入口文件index.js中导入App组件 并将它渲染到id为app的容器里:
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './modules/App'; ReactDOM.render(
<App/>,
document.getElementById('app')
);
启动应用:
npm start
浏览器打开http://localhost:8080/index.html就可以看到以下结果:
ok, 第一个 React 应用启动成功~ 下面将开始 react-router 的部分。
二. 创建一个简单的路由
Router 也是一个组件,但它不会被用来渲染任何内容
ReactDOM.render(<Router/>, document.getElementById('app'))
修改 index.js
1. 导入Router,Route,hashHistory
2. 在render中用Router代替App
下面代码中的import { Router, Route, hashHistory }是ES6导入模块的另一种用法,大括号中指定了从react-router模块里导入的变量名,变量名必须与被导入模块对外接口的名称相同。
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App'; ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={App}/>
</Router>
), document.getElementById('app'));
启动应用npm start,访问http://localhost:8080,会看到和上一节一样的结果,浏览器地址栏变成了http://localhost:8080/#/?_k=bw8nlm,这个稍后解释~
Router 组件 使用了hashHistory管理路由的历史,通过监听切换 URL 的 hash 变化来动态渲染组件。
这里的path=”/” 代表根路径,component={App} 意思是渲染组件 App。
当用户访问http://localhost:8080或http://localhost:8080/#/时,组件App将被渲染到document.getElementById(‘app’)中。
创建2个新组件:modules/About.js,modules/Repos.js
About.js:
import React from 'react'; export default class About extends React.Component {
constructor(props) {
super(props);
} render() {
return (
<div1>About</div>
);
}
}
Repos.js:
import React from 'react'; export default class Repos extends React.Component {
constructor(props) {
super(props);
} render() {
return (
<div>Repos</div>
);
}
}
然后,修改 index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App';
// 增加 About 和 Repos 组件
import About from './modules/About'
import Repos from './modules/Repos' // 增加2个新路由
ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={App}/>
<Route path="/about" component={About}/>
<Route path="/repos" component={Repos}/>
</Router>
), document.getElementById('app'));
Route 组件可以定义多个路由,访问http://localhost:8080/#/about和http://localhost:8080/#/reops会看到浏览中分别渲染About和Repos组件,可见path属性值定义了 URL 中 #号 之后的路径参数
三. 导航链接 Link 组件
Link 组件 几乎等同于<a/>标签,是应用中较常用的组件
修改 App.js,在组件App中增加一个导航:
import React from 'react';
// 导入Link组件
import { Link } from 'react-router'; export default class App extends React.Component {
constructor(props) {
super(props);
} render() {
return (
<div>
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
</div>
);
}
}
Link 组件中的to属性定义了 URL 中 #号 之后的路径参数,所以要和 Route 组件中的 path值相对应。
访问http://localhost:8080看到如下结果:
点击链接 About 会渲染组件 About,点浏览器的回退按钮 会返回渲染根组件,再点击 Repos 又会渲染组件Repos,看起来不错~
四. 嵌套路由
上节中,我们在组件App中添加了一个 导航<ul role=”nav”>…</ul>,但通常,导航应该在每个视图中都出现,在不使用 React Router 的情况下,最简单的办法就是将<ul role=”nav”>…</ul>塞到每个组件里
但在应用变的复杂时,这个办法显然 不够简洁,所以 React 提供了另一个更好的解决办法:嵌套路由,就是将Route 组件嵌套,分为两步:
第一步,修改 index.js,嵌套<Route/>:
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, hashHistory } from 'react-router'
import App from './modules/App';
import About from './modules/About'
import Repos from './modules/Repos' ReactDOM.render((
<Router history={hashHistory}>
<Route path="/" component={App}>
<Route path="/about" component={About}/>
<Route path="/repos" component={Repos}/>
</Route>
</Router>
), document.getElementById('app'));
第二步,修改 App.js,在App组件内部通过this.props.children属性嵌套进子组件:
import React from 'react';
import { Link } from 'react-router'; // 增加 this.props.children 用来渲染子组件
export default class App extends React.Component {
constructor(props) {
super(props);
} render() {
return (
<div>
<h1>React Router Tutorial</h1>
<ul role="nav">
<li><Link to="/about">About</Link></li>
<li><Link to="/repos">Repos</Link></li>
</ul>
</div> {this.props.children}
);
}
}
index.js中<Route path=”/about” component={About}/>和 <Route path=”/repos” component={Repos}/>就成为<Route path=”/” component={App}/>的子路由。访问http://localhost:8080,会先渲染App组件,点击About 后,会在App组件内部渲染About组件。
同样的,当用户访问http://localhost:8080/#/about时,先渲染App组件,然后在内部渲染About组件:
<App>
<About/>
</App> <App>
<Repos/>
</App>
本篇示例源码:
react-router-demo-part1
React-Router 中文简明教程(上)的更多相关文章
- 简单易懂的Dart》 - Dart语言中文简明教程
转自:https://www.blackglory.me/straightforward-dart/ Dart是Google公司发布的网络编程语言,其诞生的目的是为了让广大C类OOP程序员们克服Jav ...
- [转] React Router 使用教程
PS:react-route就是一个决定生成什么父子关系的组件,一般和layout结合起来,保证layout不行,内部的子html进行跳转 你会发现,它不是一个库,也不是一个框架,而是一个庞大的体系. ...
- React Router教程
React Router教程 React项目的可用的路由库是React-Router,当然这也是官方支持的.它也分为: react-router 核心组件 react-router-dom 应用于浏览 ...
- 基于R语言的结构方程:lavaan简明教程 [中文翻译版]
lavaan简明教程 [中文翻译版] 译者注:此文档原作者为比利时Ghent大学的Yves Rosseel博士,lavaan亦为其开发,完全开源.免费.我在学习的时候顺手翻译了一下,向Yves的开源精 ...
- React Router 使用教程
一.基本用法 React Router 安装命令如下. $ npm install -S react-router 使用时,路由器Router就是React的一个组件. import { Router ...
- React Router基础教程
React是个技术栈,单单使用React很难构建复杂的Web应用程序,很多情况下我们需要引入其他相关的技术 React Router是React的路由库,保持相关页面部件与URL间的同步 下面就来简单 ...
- Lisp简明教程
此教程是我花了一点时间和功夫整理出来的,希望能够帮到喜欢Lisp(Common Lisp)的朋友们.本人排版很烂还望多多海涵! <Lisp简明教程>PDF格式下载 <Lisp简明教程 ...
- CSDN Markdown简明教程4-UML画画
0.文件夹 文件夹 前言 序列图 1 序列图演示样例 2 序列图语法 流程图 1 流程图演示样例 2 流程图语法 节点定义 节点连接 Gravizo 声明 1. 前言 Markdown是一种轻量级的标 ...
- 【前端】vue.js环境配置以及实例运行简明教程
vue.js环境配置以及实例运行简明教程 声明:本文档编写参考如下两篇博客,是对它们的修改与补充,欢迎点击链接查看原文: 原文1:vue.js在windows本地下搭建环境和创建项目 原文2:Vue. ...
随机推荐
- Laravel5.1学习笔记11 系统架构3 服务提供者
服务提供者 简介 写一个服务提供者 Register注册方法 Boot 方法 注册提供者 缓载提供者 简介 Service providers are the central place of all ...
- [ HNOI 2006 ] 公路修建问题
\(\\\) \(Description\) 一个\(N\)个点\(M\)条边的图,每条边可以选择\(w_i,p_i\)两个边权之一,现求一个生成树上的最大边权最小值,要求这棵生成树上至少有\(K\) ...
- ionic2/3 禁止屏幕旋转,禁止横屏,竖屏
ionic2/ionic3禁止屏幕旋转,及解除禁止旋转 1.添加插件: cmd到项目目录---> cordova plugin add cordova-plugin-screen-orienta ...
- MYSQL 使用自定义表变量
mysql 用户自定义表变量,ENGINE=MyISAM DEFAULT CHARSET=gb2312; 制定编码方式,防止乱码 DROP TABLE IF EXISTS p_temp; creat ...
- hibernate映射数据库时@ManyToOne和@OneToMany
第一次用hibernate自动生成表,涉及到多个表的外键,用到了@OneToMany和@ManyToOne注解碰到了几个错误. 首先声明一个基础,@OneToMany和@ManyToOne两个注解没有 ...
- Mysql 在Linux下的安装
1.获取mysql源码 wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.49.tar.gz 3.添加mysql用户和用户组,创建 ...
- Oracle 【基 本 操 作】
1.日期时间 select SYSDATE from DUAl; select TO_CHAR(SYSDATE, 'YYYY-MM-DD') from DUAL; select TO_CHAR(SYS ...
- Asp.NET误人子弟教程:在MVC里面结合JQ实现AJAX
public class Person { public string Name { get; set; } public string City { get; set; } public strin ...
- Django REST framework - 版本控制
目录 Django REST framework 版本控制 为什么需要版本控制 DRF提供了5种版本控制方案 版本控制系统的使用 全局配置 局部配置 获取版本信息 Django REST framew ...
- codeforeces近日题目小结
题目源自codeforeces的三场contest contest/1043+1055+1076 目前都是solved 6/7,都差了最后一题 简单题: contest/1043/E: 先不考虑m个限 ...