如今用react写单页应用基本上都是用react-router作前端路由了吧!最近在使用react-router的过程当中遇到了很多问题,在这里总结一下。前端
浏览器urlreact
react-router默认提供的history是 createHashHistory ,即它用到的是 URL 中的 hash(#
)部分去建立形如 example.com/#/some/path
的路由,因此你会看到url多了相似 _key=s1gvrm 的 query,这真的很难看。并且这也不是官方在实际生产应用中所推荐的。要改变这种状况的话,咱们须要去使用
createBrowserHistory ,在咱们的代码中引入history,并在Router组件处调用
createBrowserHistory 方法便可。
webpack
import React from "react"; import ReactDOM from "react-dom"; import createBrowserHistory from "history/lib/createBrowserHistory" import { Router,Route,Link,browserHistory,IndexRoute,IndexLink } from "react-router"; class App extends React.Component{ render(){ return( ... ); } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> ... </Router> ),document.getElementById("app"));
其实关于url还有许多的细节,由于react-router自己就是构建于history之上的。单页应用的url只不过是针对于react- router的一个标示而已,界面间的跳转全然由react-router决定,react-router检查当前url随后渲染匹配的路由组件,由于是前端路由,因此若是直接在浏览器上输入相对应的组件url,然后端却不对此url作任何的匹配的话,可能会获得404响应。web
组件通讯后端
这是一个用react写代码永远都绕不开的话题。react-router是基于react开发的,因此它的每个route都是一个组件。路由组件间的通讯通常借由Link来实现,而根据路由参数的不一样,还能够分红两种。这个很容易理解,由于这两种方式和咱们平时写的后台路由并无什么太大差异。浏览器
1 param,param经过/:param的方式传递。session
好比说咱们如今有一个显示消息列表的路由组件,咱们须要在点击每个消息的时候能跳转到显示被点击消息详情的路由组件。这个时候咱们消息详情路由组件能够是这样定义的:react-router
<Route path="News_detail/:news_id" component={ news_detail }/>
在消息列表路由组件那里咱们让每一条消息都是这样的一个Link:架构
<Link to={ `News_detail/${ element.timestamp }` } >{ element.news }</Link>
2 queryapp
<Link to="/Activity_Publish" query={{ timestamp : element.timestamp }}>编辑</Link>
var { query } = this.props.location; var timestamp = query.timestamp;
获取到query参数。
相对于param,局限性更小,你能够根据须要传递更多的参数,只不过有点相似于get请求,传递的参数会附带在url后面,看起来有点丑,并且几乎无隐蔽性可言。
3 state
这种方式借助了location 对象,
location 对象
能够简单的认为是 url 的对象形式表示,这里要提的是 location.state
,每一个 URL 都会对应一个 state 对象,你能够在对象里存储数据,但这个数据却不会出如今 url 中。实际上,数据被存在了 sessionStorage 中,旧的路由组件能够借助这种方式传递数据给新的路由组件,可是会有个问题就是,新的路由组件虽然在首次被渲染的时候能够成功拿到数据,可是若是此时浏览器被刷新的话,传递过来的数据也会消失。
<Link to="/Activity_Publish" state={{ timestamp : element.timestamp }}>编辑</Link>
按需加载
react-router协同webpack的使用能够实现组件的按需加载,并且 这种按需加载彻底是异步的,这点特别酷炫,你再也不须要一口气加载那么大的js文件,即便里面包含着许多用户甚至都不会使用到的web组件。你能够只根据需 要加载用户浏览的那些组件,这个举措将会帮你大大的下降首屏渲染的时间。
实现这个功能很简单,好比在一开始你的路由是这样子的:
...
import News_detail from "./marriage_component/activity/news_detail.jsx"; ... class App extends React.Component{ render(){ ... } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> <Route path="/marriage_app" component={ App }> ... <Route path="/marriage_app/News_detail/:news_id" component={ News_detail }/> ...
把它改为这样就好了:
...
//import News_detail from "./marriage_component/activity/news_detail.jsx"; ... class App extends React.Component{ render(){ ... } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> <Route path="/marriage_app" component={ App }> ... <Route path="/marriage_app/News_detail/:news_id" getComponent={ (nextState, callback) =>{ require.ensure( [ ], (require) => { callback(null, require("./marriage_component/activity/news_detail").default) }) } }/> ...
一开始的组件再也不须要被导入,webpack会帮你在须要的时候引入它。
最后
这种先后端分离的模式真的很赞,但彷佛对SEO并非很友好。若是真的须要SEO,又追求于实现先后端的真正解耦,是否是以Nodejs为中间层的架构模式会成为一种解决方案呢?