React-Router 中文简明教程(中)
本篇示例源码:
react-router-demo-part2
五. 为 Link 组件设置触发状态
有时我们需要在导航链接上设置一个触发状态的样式,让用户知道当前在哪个路由下,比如某宝的底部导航:
一种方法 是使用Link组件的activeStyle属性直接设置行内样式,修改modules/App.js中:
注意:React 组件的样式属性值必须写在双括号内,这是因为样式在 JSX 语法里被作为一个对象。
另一种更好的方法 是使用Link组件的activeClassName属性,为被触发的导航链接添加一个 Class:
在index.html里简单定义下.active:
手动刷新http://localhost:8080 因为 Webpack-dev-server 的热替换功能 不会作用于index.html。
点击 About 或 Repos,被触发的导航链接会变为红色:
除了站点导航的一级链接,站点里的大部分链接 一般并不需要知道是否被触发,如果将导航链接单独提取为一个组件,你就不用担心因为activeClassName和activeStyle属性的到处存在 而难以维护。
创建modules/NavLink.js,代码如下:
// modules/NavLink.js import React from 'react' import { Link } from 'react-router' export default class NavLink extends React.Component { constructor(props) { super(props); } render() { return ( ); } }
这里的…this.props点点点,使用了延展操作符(spread operator),它可以传递一组属性键值对给
修改modules/App.js,导入./NavLink 并将< Link/ >
换成< NavLink/ >
// NavLink import NavLink from './NavLink'; // ...
六. URL 参数
来看下面的 URL:
/repos/reactjs/react-router /repos/facebook/react
这些 URL 可以匹配如下这样的路由路径:
/repos/:userName/:repoName
其中:后面的部分为参数,它的具体值可以通过路由组件的this.props.params[name]属性获取到
首先,创建modules/Repo.js:
// modules/Repo.js import React from 'react'; export default class Repo extends React.Component { constructor(props) { super(props); } render() { return (//编辑器问题h2标签添加了空格,复制代码请自行删除空格 < h2 >{this.props.params.repoName}< /h2 >); } }
这里的this.props.params.repoName是为了获取路由路径——/repos/:userName/:repoName中repoName的具体值。
修改index.js,添加 Repo 路由,path属性指定了路由的 匹配规则,这里设为/repos/:userName/:repoName
// ... // import Repo import Repo from './modules/Repo' ReactDOM.render((), document.getElementById('app')); {/* Repo Route */}
修改 modules/Repos.js,添加一些链接:
// ... import { Link } from 'react-router' export default class Repos extends React.Component { constructor(props) { super(props); } render() { return (//编辑器问题h2标签添加了空格,复制代码请自行删除空格 < h2 >Repos< /h2 >); } }
- React Router
- React
测试下结果,首页确保你的静态服务器是开启状态 如果没有就运行npm start
访问http://localhost:8080/#/repos/可以看到:
点击链接 React Router 会渲染Repo组件:
可以看到Repo组件的内容为:react-router,正是通过this.props.params.repoName属性获取到路由匹配规则/repos/:userName/:repoName中参数:repoName的具体值,即 URL 中/repos/reactjs/react-router的 react-router 字段。
另外,路由 path 属性的常用 匹配规则(参考了阮一峰的 React-Router 教程资料)如下:
path | 匹配 | 说明 |
---|---|---|
path=”/hello/:userName” | /hello/nicholas /hello/jack |
:paramName匹配 URL 的一个部分,直到遇到下一个/,?,#为止。这个路径参数可以通过this.props.params.paramName获取 |
path=”/hello(/:userName)” | /hello /hello/nicholas /hello/jack |
()表示 URL 的这个部分是可选的 |
path=”/hello/*” | /hello/nicholas /hello/nicholas/jack /hello/index.html |
*匹配任意字符,直到模式里面的下一个字符为止,匹配方式为非贪婪模式 |
path=”/**/*.jpg” | /hello/test.jpg /react/hello/to/a.jpg |
**匹配任意字符,直到遇到下一个/,?,#为止,匹配方式为贪婪模式 |
七. 多层嵌套路由
< router >还可以多层嵌套,上一节示例中当点击 Repos 的子导航链接 React Router 整个子导航区域会被内容渲染所替代,如果想查看 React 的内容,就必须点击浏览器回退按钮,这显然不利于用户体验。我们来改进下,让子导航始终存在,将内容部分放在导航下面显示
首先,在index.js中将Repo路由嵌套进Repos路由内部:
接着在modules/Repos.js中添加this.props.children属性,将Link组件换成之前我们封装的NavLink组件,链接的触发状态也有了:
// ... // import NavLink import NavLink from './NavLink' export default class Repos extends React.Component { constructor(props) { super(props); } render() { return (< h2 >Repos< /h2 > {/* 将 Link 换成 NavLink */}); } }{ this.props.children }
React Router React
ok 测试下,点击链接 React-Router 结果如下:
八. IndexRoute 组件
// modules/App.js // ... render() { return (); }React Router Tutorial
{this.props.children}
// index.js // ... ReactDOM.render((), document.getElementById('app'));
上面代码,当访问 根路径/(即http://localhost:8080/#/) 时,页面并没有渲染任何子组件,因为此时App组件中的{this.props.children}获取到的值为undefined,如图:
我们可以用{this.props.children || < Home/>}来解决这个问题,在this.props.children为空时渲染Home组件,创建modules/Home.js:
// modules/Home.js import React from 'react'; export default class Home extends React.Component { constructor(props) { super(props); } render() { returnHome} }
在modules/App.js中增加{this.props.children || < Home/>}:
// modules/App.js // ... render() { return (); }React Router Tutorial
{this.props.children ||}
上面的办法虽然能解决问题,但显然不优雅,应该将Home组件放到路由中。将modules/App.js中的{this.props.children || < Home/>}还原为{this.props.children}。
修改index.js,使用 IndexRoute 组件作为首页路由:
// index.js // ... import { Router, Route, hashHistory, IndexRoute } from 'react-router'; import Home from './modules/Home'; ReactDOM.render(({/* 添加 IndexRoute 组件 */} ), document.getElementById('app'));
访问根路径http://localhost:8080,测试结果如图:
九. IndexLink 组件
你有没注意到,在我们的app中还缺少一个能切换渲染Home组件的导航链接?
尝试在modules/App.js中添加一条< NavLink/>,将to属性设为/根路径:
测试时你会发现无论点击哪个导航链接,Home 链接始终处于激活状态(如图,点击 About 后):
因为,当子路由处于激活状态时 父路由也会被激活,而/路径可以匹配任何子路由,解决办法是使用 IndexLink 组件,修改 modules/App.js,增加activeClassName属性:
// ... import { IndexLink } from 'react-router'; export default class App extends React.Component { constructor(props) { super(props); } render() { return (); } }React Router Tutorial
{this.props.children}
这里有个小问题,只有在精确匹配到根路由时,Home 链接的activeClassName属性才生效。
另一个方法是直接使用Link组件的onlyActiveOnIndex属性来达到同样效果,语法如下:
之前我们已经将导航链接Link组件封装成了NavLink组件,这里就只需在NavLink组件上增加onlyActiveOnIndex属性,修改modules/App.js:
import React from 'react'; import NavLink from './NavLink'; export default class App extends React.Component { constructor(props) { super(props); } render() { return (); } }React Router Tutorial
{this.props.children}
本篇示例源码:
react-router-demo-part2
原文地址:http://www.mrfront.com/2016/12/23/react-router-tutorial-part2/
相关推荐
-
对于react-redux的理解梳理 框架
2019-3-9
-
node配置微信小程序解密消息以及推送消息 框架
2019-10-8
-
vue 全局环境切换 框架
2019-11-1
-
NodeJS之path模块 框架
2019-8-17
-
Vue.js基础 框架
2019-3-14
-
【极简版】SpringBoot+SpringData JPA 管理系统 框架
2019-4-15
-
一篇文章教你如何捕获前端错误 框架
2019-9-1
-
Vue路由之JWT身份认证 框架
2019-9-1
-
Vue的钩子函数[路由导航守卫、keep-alive、生命周期钩子] 框架
2018-7-25
-
业内首个 React Native转微信小程序引擎 Alita 正式发布 框架
2019-6-1