为更加理解和掌握 React Router v4, 我在上创建了 demo 项目用来实践 React Router v4 https://reacttraining.com/react-router/web .
介绍
React Router v4 是一个完全使用 react 重写的 React 包, 所有的东西都仅仅是组件. 跟 react router 之前的版本理念都不一样了.
安装
React Router 现在已经被划分成了 3 个包: react-router,react-router-dom,react-router-native.
不应该直接安装 react-router 包, 这个包为 React Router 应用提供了核心的路由组件和函数, 另外两个包提供了特定环境的组件 (浏览器和 react-native 对应的平台), 不过他们也是将 react-router 导出的模块再次导出.
本项目在 Web 中应用, 因此使用 react-router-dom
- NPM install --save react-router-dom
- Router
开始一个新项目时, 决定要使用那种 Router,<BrowserRouter> or <HashRouter>.
这两区别在于:
BrowserRouter: 一般用来处理动态页面, 适合用户互动多的网站.
HashRouter: 一般用来处理静态页面, 适合用于展示型的网站, seo 的时候一般建议静态网页. 地址栏中会多一个 #(exp: http://localhost:3000/#/electionic )
我们的项目页面都是服务器动态生成的, 因此我们的 router 使用 < BrowserRouter>, 在 index.JS 中使用.
- import {
- BrowserRouter
- } from 'react-router-dom';
- , document.getElementById('root'));
history 对象
history 对象由 Router 创建, 用来保持对当前位置的追踪还有页面发生变化时候重新渲染页面.
basename 属性
页面如果部署在二级目录, 可加加 basename='/xlj',
打开的地址栏: http://localhost:3000/xlj/electionic
Routes
Routes 组件是 React Router 的重要组成部分. 用来在路径符合的时候在某个地方渲染某个组件.
匹配路径
React Router 包使用 path-to-regexp 包来判断当前 path 是否匹配当前的 pathname. 它的原理是: 将 path 字符串转换成正则表达式与当前的 pathname 进行匹配.
当 path 与 pathname 匹配的时候, 一个具有以下属性的 match 对象将会被作为 prop 传入:
match.url : 当前的 path 与 pathname 相匹配的部分. Clothes.JS 中的 path 就是 / clothes,pathname 是 / clothes/woman 的时候, 匹配的部分就是 / clothes.
match.path : 路由 path.
match.isExact : path === pathname.
match.params : 一个包含着 pathname 被 path-to-regexp 捕获的对象.
exact
下面代码块中要加 exact, 不加 exact 的话, 下面的三个 url 都会匹配到第一行中的 path="/clothes", 即渲染的都是 Woman 组件. 除非换顺序, 把 path='/clothes'换到最后面.
- http://localhost:3000/clothes
- http://localhost:3000/clothes/woman
- http://localhost:3000/clothes/man
Route 渲染组件内容
直接定义 component 属性
通过 render 渲染组件
()} />
这两种方法原理都是通过 React.createElement 来引入组件. 一般情况用 component 就够了. 但是通过 render 来定义可传入自定义属性. 比如这里的 data 属性. 如果不用 render, 只有默认的 props.
由 routes 渲染的组件默认有 props, 包含 match,location,history(由 router 创建)
嵌套路由
4.0 之前定义嵌套组件不是 React 的风格, 是伪组件; 4.0 之后是一切皆组件.
4.0 之前:
4.0 之后:
本项目中 Clothes.JS 和 Man.JS 中分别嵌套了二级和三级路由.
本项目中 Fruites.JS 中用路径参数捕获 / fruites 后面带的 pathname 部分. 对于 / fruites/abc 的路径, 都能匹配到 FruitesTemplate 组件. 在 FruitesTemplate 组件中, 使用 this.props.match.params.type 即可获取到对应的 abc 部分.
动态路由
Clothes.JS 中, 用 this.props.match.url 代替 / clothes, 这样就不用写死了.
大专栏 React Router v4 学习笔记 pan>
const url = this.props.match.url;
跳转
- Link
- import {
- Link
- } from 'react-router-dom'
ps: 这里的 state 只在 pathname === match url 时才会有
NavLink
NavLink 比 Link 有更丰富的 API. 可以在当前的 NavLink 上添加对应选中时候的样式 activeClassName.
- import { NavLink } from 'react-router-dom'
- // 参考 Electric.JS
- this.props.history
- this.props.history.push({
- pathname: '/xlj',
- search: '?id=1&code=2'
- });
- this.context.router.history
先当前组件中引入 contextTypes 属性, 才能获取到 context 下的 router.
- import PropTypes from 'prop-types';
- clicktest = () => {
- this.context.router.history.push({
- pathname: '/xlj',
- search: '?id=1'
- })
- }
- purchasDetails.contextTypes = {
- router: PropTypes.object
- }
- Switch
如下代码: 加上 Switch 标签, 在页面中只渲染出当前匹配的 dom, 匹配到一个之后就不忘下走了. 不加 Switch, 在 http://localhost:3000/clothes/woman 中会渲染出两个 Woman 组件.
Redirect
Redict 标签一般用于没有匹配到 path 的时候, 默认跳转到的路径.
参考文档
[译] 简明 React Router v4 教程 https://juejin.im/post/5a7e9ee7f265da4e7832949c
4.0 教程 http://reacttraining.cn/web/example/basic
React Router 4 简介及其背后的路由哲学 https://juejin.im/post/5a641747518825732d7fb25f
来源: http://www.bubuko.com/infodetail-3407664.html