安装
前置
首先需要安装 Node.js 环境 和包管理器 npm
Clone例子
git clone https://github.com/BerlinChan/react-router-tutorial-cn.git
cd react-router-tutorial-cn
cd lessons/01-setting-up
npm install
npm start
测试
在浏览器中打开网址 http://localhost:8080
在浏览器中应该看到 “Hello React Router”
修改modules/App.js,修改后浏览器会自动重载更新
初看代码
|
|
渲染路由
添加hashHistory
React Router 实质上就是一个组件
|
|
配置一个路由,打开index.js
|
|
命令行中输入 npm start 运行服务后, 在浏览器中访问 http://localhost:8080
URL 中多了一串乱七八糟的字符。 这是因为我们使用了 hashHistory, 它的作用是: 在 URL 中添加 hash 值来管理路由历史
添加更多屏幕显示
创建 2 个新组件
- modules/About.js
- modules/Repos.js
|
|
修改index.js
|
|
现在访问 http://localhost:8080/#/about 和 http://localhost:8080/#/repos
使用链接导航
最常用的组件也许就是 Link
使用 来导航非常相似,只是它链接的内容是由 Router 渲染到页面上
|
|
现在访问 http://localhost:8080,点击上面的链接,然后点浏览器的前进、后退
嵌套的路由
React Router 的路由嵌套提供了另外一种方法来实现 UI 复用
复用导航栏
将 About 和 Repos 组件嵌套进 App 中, 这样我们就能将导航栏复用到本应用程序所有的界面显示中
首先,移动其他的路由到 App Route 其下,成为 App 的子组件
|
|
然后,在 App 中渲染子组件
|
|
现在点击链接并观察,当路由改变的时候, App 组件通过 this.props.children 将对应的子组件渲染到界面上
激活项 Link
Link 与 a 的一个不同之处就是,它知道它自身是否为当前激活项, 并将自己的样式与非激活项区分开
激活项样式
在 Link 中添加 activeStyle 属性
|
|
活动项类名
使用一个活动项类名 activeClassName 代替内联样式
|
|
从外部文件中引用,若 Webpack 没有编译 index.html,你需要手动刷新浏览器来呈现上面的代码修改
|
|
包裹导航栏 Nav 中的 Link
将 activeClassName 或 activeStyle 包裹到组件中
用扩展运算符,它的写法是 …
扩展运算符传递父组件所有props到组件中,与activeClassName一同成为该组件的props
创建 modules/NavLink.js
|
|
替换 App 中的 Link 为 NavLink
|
|
URL 参数
以 : 开头的部分就是 URL 参数名,参数值会被解析成 URL 中匹配的字符, 这个值可通过路由组件中的 this.props.params[参数名] 来访问
|
|
添加一个带参数的路由组件
首先需要有个组件,当进入这个路由的时候显示相应内容, 新建文件 modules/Repo.js
|
|
到 index.js 中添加新路由
|
|
在 Repos.js 中添加一些链接地址并指向新添加的路由
|
|
路由中 path 的值成为子组件中的 props。 repoName 和 userName 都可以在组件中通过 this.props.params 访问到
更多嵌套
点击 Repos 下的二级导航后,二级导航链接列表会消失
让二级导航链接一直显示,就像全局导航栏
首先,嵌套 Repo 到 Repos 路由下。 然后在 Repos 中渲染 this.props.children
|
|
活动项 Links
把之前添加的 NavLink 组件用上,用于为活动项链接添加类名 active
|
|
页面最上面全局导航的 /repos 链接和其下的二级导航 repo 都被标示为活动项,当子元素为活动项时,其父元素当然也是活动项
首页路由
当访问这个应用的 / 地址时,渲染 Home 首页界面
先创建 Home 组件,然后讨论如何将其指定为 / 时渲染
|
|
一种做法是检查 App 中是否有子元素, 若没有的话就渲染 Home 组件
|
|
访问到首页的时候, 是像访问 About 和 Repos 时候那样被路由指定进入的
更加利于将 Home 从 App 中解耦,让路由配置决定应该渲染什么子元素
|
|
现在打开 http://localhost:8080,新添加的 Home 组件被渲染了
IndexRoute 中没有指定 path 属性
当没有其他的子元素匹配路由的时候,它指向的组件会成为父元素的 this.props.children 被渲染, 这其实也是路由精确匹配所得到的结果
用类比的方式来帮助理解: 当你访问 / 的时候, web 服务器会去找 index.html 页面,React Router 是一样的, 当路由路径匹配到 / 的时候, 去找首页路由
首页链接
添加链接可以链接返回到Home组件
Home 的链接总是显示为激活项
|
|
IndexLink
使用 IndexLink 链接到首页路由
当我们访问到首页路由的时候, 这个链接才会被标示为激活项
|
|
onlyActiveOnIndex 属性
为 Link 添加 onlyActiveOnIndex 属性也可以达到一样的效果
|
|
在 NavLink 组件中, 我们使用 {…spread} 扩展运算符, 传递父组件所有的 props 给其中的 Link
这样当渲染一个 NavLink 组件的时候, 其中的所有 props 都能传递到 Link 组件中
|
|
清理浏览器历史的 URL
现代浏览器允许 JavaScript 脚本操作 URL 而不发起新的 http 请求, 因此不必再依赖 hash (#) 作为 URL 的一部分来实现路由
配置浏览器历史
打开 index.js 将导入的 hashHistory 替换成 browserHistory
|
|
配置你的服务器
不论访问什么 URL, 服务器都应该响应返回你的应用程序, 因为应用程序是在浏览器中解析 URL 并操作路由
当前我们的服务器不知该如何处理不同的 URL, 于是返回了Cannot GET /repos
Webpack Dev Server 有一个选项, 用来使服务器总是响应返回应用程序
打开 package.json 然后添加 –history-api-fallback
|
|
index.html 中的相对路径改成绝对路径
|
|
配置生产环境服务器
Webpack dev server 不是用于生产环境的服务器,建立一个生产环境服务器, 然后写一个用来识别不同环境, 启动相应服务器的脚本
安装一些模块
|
|
运行 npm start 的时候, 脚本会检查 NODE_ENV 的值是否为 production
如果是的, 脚本会运行 npm run start:prod, 反之则是运行 npm run start:dev
|
|
使用 Express 创建一个生产服务器, 建立配置文件 server.js, 放根目录
|
|
运行
|
|
导航到 http://localhost:8080/package.json,直接暴露配置文件信息
移动一些文件, 然后修改静态文件路径配置
- 建立一个 public 目录
- 移动 index.html 和 index.css 到该目录下
修改 server.js, 将静态文件目录指定到正确的位置
|
|
修改 webpack 的配置, 告诉它构建的目标路径
|
|
修改package.json,在 npm run start:dev 后面添加 –content-base 参数
|
|
现的服务器不会伺服 public 目录之外的文件了, 最后再为 webpack 加上代码压缩的配置, 并给 express 配置上 gzip 压缩
|
|
express 服务器配置压缩
|
|
以生产环境模式来启动服务
|
|
编程实现导航
大部分的导航链接使用 Link 实现, 但你也可以编程实现应用程序中的导航, 比如响应表单的提交、按钮的点击
|
|
将 browserHistory 传递到文件 index.js 内的 Router 当中, 然后推送一个新的 URL 到浏览历史中从而渲染新的内容
|
|
利用 React 的”上下文特性” 来直接使用父组件 index.js 中 Router 提供的 router
首先在组件中关联上下文, 然后使用它
|
|
服务器渲染
在 React 中, 服务器渲染是一个简单的核心概念
|
|
webpack 来打包生成一个运行在服务器端的应用包,创建名为 webpack.server.config.js 的配置文件
|
|
更新 package.json 配置
|
|
运行命令行,服务器端也能运行应用并渲染页面
|
|
为了让路由在服务器端与客户端都可以运行, 我们需要将它放到一个单独的模块中
创建文件 modules/routes, 然后将路由配置移动到其中
|
|
修改index.js
|
|
打开文件 server.js,从 React Router 中导入 match 和 RouterContext, 这样路由就会先根据 URL 完成匹配, 然后完成渲染
|
|
运行命令行
|
|
实际生产环境的回调如下
|
|