谈谈 react-router
谈谈最近使用的 React + webpack 来开发项目,感觉确实是爽的飞起,然而总感觉还是少了点什么。
概述先贴上官方文档 https://github.com/rackt/react-router/tree/master/docs. 浏览器支持所有支持 React 的浏览器。 安装npm install react-router@latest 同时,react-router 是基于 history 开发的,这里你需要安装 history。 npm install history@1.13.1 构建工具的话,我依然建议是 webpack , React 和 webpack 是一对好兄弟。 npm install webpack webpack的使用方法可以看我的前两篇文章:
小例子// 加载依赖包,这是 es6 的语法(我好啰嗦)。 import React from 'react' import { render } from 'react-dom' // 这里从 react-router 引入了三个组件,先不解释。 import { Router,Route,Link } from 'react-router' const App = React.createClass({ render() { return ( <div> <h1>App</h1> <ul> <li><Link to="/about">About</Link></li> <li><Link to="/inbox">Inbox</Link></li> </ul> {this.props.children} </div> ) } }); const Inbox = React.createClass({ render() { return ( <div> Inbox </div> ) } }); const About = React.createClass({ render() { return ( <div> About </div> ) } }); render(( <Router> <Route path="/" component={App}> <Route path="about" component={About} /> <Route path="inbox" component={Inbox} /> </Route> </Router> ),document.getElementById('root')); 我就偷个懒把官方文档的demo直接copy了。 不想用 jsx 来写,换个方式吧~以上例子可以改写成: ... const routerConfig = [ { path: '/',component: App,childrenRoutes: [ { path: 'about',component: About },{ path: 'inbox',component: Inbox },] } ]; render(( <Router routes={routeConfig} /> ),document.getElementById('root')); 这里的结构就更清晰了,我是比较喜欢这种方式。 默认的路由比如上面的例子,/ 对于的组件是 App,如果 App 只是渲染了一个导航条,却没有自组件,那打开 比如 qiutc.me/ 的时候不是就没有内容了吗。 ... // 添加组件 Index const Index = React.createClass({ render() { return ( <div> Index Index Index </div> ) } }); // 修改配置 const routerConfig = [ { path: '/',indexRoute: { component: Index },] } ]; 这里加了一个 { path: 'about',component: About,indexRoute: {component: AboutIndex} }, 以此类推。 404 NotFound如果我们打开了一个没有设置路由的链接,就必然需要一个友好的 404 页面。配置如下: ... // 添加 404 组件 const NotFound = React.createClass({ render() { return ( <div> 404 NotFound </div> ) } }); // 修改配置 const routerConfig = [ { path: '/',] },{ path: '*',component: NotFound,} ]; 如此简单。 绝对路径与重定向const routerConfig = [ { path: '/',{ path: 'inbox',component: Inbox,childrenRoutes: [ { path: 'message/:id',component: Message,} ],},} ]; 在这里我们访问 /inbox/message/1 对于渲染 Message 组件,这个链接太长了,我们想直接 /message/1 那怎么办,改路由结构?太麻烦了!绝对路径可以帮你做到这个。 const routerConfig = [ { path: '/',childrenRoutes: [ { path: '/message/:id',{ path: 'message/:id',onEnter: function (nextState,replaceState) { replaceState(null,'/messages/' + nextState.params.id); } } ],} ]; onEnter 方法表示进入这个路由前执行的方法,在进入 /inbox/messages/:id 的前,执行function (nextState,replaceState) { replaceState(null,'/messages/' + nextState.params.id); }
同样的也有 onLeave 这个方法表示在离开路由前执行。 import { Redirect } from 'react-router' React.render(( <Router> <Route path="/" component={App}> <IndexRoute component={Index} /> <Route path="about" component={About} /> <Route path="inbox" component={Inbox}> <Route path="/messages/:id" component={Message} /> {/* 跳转 /inbox/messages/:id 到 /messages/:id */} <Redirect from="messages/:id" to="/messages/:id" /> </Route> </Route> </Router> ),document.getElementById('root')) 路径匹配原理嵌套关系
简单来讲,就是说,匹配的时候会先匹配到外层路径,然后依次遍历到内层。 tip:使用绝对路径可以忽略嵌套关系,如上面例子。 路径语法路由路径是匹配一个(或一部分)URL 的 一个字符串模式。大部分的路由路径都可以直接按照字面量理解,除了以下几个特殊的符号:
优先级最后,路由算法会根据定义的顺序自顶向下匹配路由。因此,当你拥有两个兄弟路由节点配置时,你必须确认前一个路由不会匹配后一个路由中的路径。例如: <Route path="/comments" ... /> <Redirect from="/comments" ... /> 第二个是不会被执行的。 拿到参数路径的比如上面的 /messages/:id ,这个id可能是我们在 Message 获取数据时需要的 id。 const Message = React.createClass({ render: function() { return ( <div>{ this.props.params.id }</div> ); } }); 这样就可以获取到了。 history 配置React Router 是建立在 history 之上的。 简而言之,一个 history 知道如何去监听浏览器地址栏的变化, 并解析这个 URL 转化为 location 对象, 然后 router 使用它匹配到路由,最后正确地渲染对应的组件。
这三个有什么区别呢:createHashHistory这是一个你会获取到的默认 history ,如果你不指定某个 history 。它用到的是 URL 中的 hash(#)部分去创建形如 example.com/#/some/path 的路由。 createBrowserHistoryBrowser history 是由 React Router 创建浏览器应用推荐的 history。它使用 History API 在浏览器中被创建用于处理 URL,新建一个像这样真实的 URL example.com/some/path。 Memoryhistory不会在地址栏被操作或读取。 使用import { createBrowserHistory,useBasename } from 'history'; const historyConfig = useBasename(createHistory)({ basename: '/' // 根目录名 }); ... render(( <Router routes={routeConfig} History={historyConfig} /> ),document.getElementById('root')); Link&IndexLinkLink我们在最开头看到这样一个东西: const App = React.createClass({ render() { return ( <div> <h1>App</h1> <ul> <li><Link to="/about">About</Link></li> <li><Link to="/inbox">Inbox</Link></li> </ul> {this.props.children} </div> ) } }); Link 会被渲染成 a ,to 其实就是 href , 参数:
query={{q: "que"}} 对应 `/example?a=que 这里的 query 同样可以像 params 会被传入下一个路由组件的 props
hash={111} 对应 `/example#111 这里的 query 同样可以像 params 会被传入下一个路由组件的 props
在 /index 下 <Link to="/index" activeClassName={"active"} activeStyle={{color: 'red'}} >/</Link> 这里渲染出来的 a 标签会有一个激活的 active 类名,还会有一个颜色 red <Link to="/about" activeClassName={"active"} activeStyle={{color: 'red'}} >/</Link> 这里渲染出来的 a 标签就不会有以上属性
IndexLink在上面有一个问题如果: 在 / 下 和 /index <Link to="/" activeClassName={"active"} activeStyle={{color: 'red'}} >/</Link> 这个 Link 渲染出来的 a 标签都会激活 active 属性,并且会带上 color: 'red' 因为 / 和 /index 和 / 都是匹配的 这时候就可以用: <IndexLink to="/" activeClassName={"active"} activeStyle={{color: 'red'}} >/</IndexLink> 只会在 / 下呗激活,在 /index 或者其他下面,不会被激活 未完待续关于 根据路由按需异步加载js 和 服务器端渲染路由视图 以及 react-router的更高级用法 会在下一篇文章来探讨。毕竟哥也需要去深入研究一下才敢献丑。? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |