使用react 作开发,避免会使用react-routercss
React Router
目前已经被划分红了三个包:react-router
,react-router-dom
, react-router-native
。
React Router 应用提供了核心的路由组件和函数,另外两个包提供了特定环境的组件(浏览器和 react-native 对应的平台),不过他们也是将 react-router 导出的模块再次导出。html
react-router-dom
做为浏览器的平台,是咱们的作WEB首选。react-router-dom
能够选择 <BrowserRouter>
和 <HashRouter>
组件前端
<BrowserRouter>
应该用在服务器处理动态请求的项目中(知道如何处理任意的URI)
<HashRouter>
用来处理静态页面(只能响应请求已知文件的请求)。node
假若有一个 Link 标签,点击后跳转到 /test/guide。react
BrowserRouter: http://localhost:8080/test/guide
HashRouter: http://localhost:8080/#/test/guide
webpack
一般来讲更推荐使用
现现在,前端开发避免不了本地服务开发,大多数会选择node作本地服务开发层,其中包括了koa,express。webpack作本地服务webpack-dev-server(也是一个express的服务)
有本地服务就避免不了本地路由。本地服务的get URL请求如何和react-router作适配呢?请往下看。express
HashRouter作本地开发,主要是 hash 地址,hash 地址就是指 # 号后面的 url。这个功能只会实现静态页面的跳转,不会产生路由的变化
如上面例子HashRouter: http://localhost:8080/#/test/guide
,对于服务端而言,路由实际仍是再根目录下'/' ,而“#/test/guide” 只是hash地址,能够经过浏览器location 命令查看
由于对于服务端而言,路由实际上没有发生GET请求变化,以致于服务端不会发生响应,也不会存在Cannot GET页面提示404等问题。react-native
其中若是是webpack服务,关于设置historyApiFallback:true
网上有不少的文章,给了这个答案,来处理本地服务问题promise
首先 devServer.historyApiFallback
用来应对返回404页面时定向到特定页面用的
若是你在webpack配置文件中修改了 output.publicPath 值默认为'/',那么你就须要声明请求重定向,配置historyApiFallback.index 值。
// output.publicPath: '/assets/' historyApiFallback: { index: '/assets/' }
关于BrowserRouter 和本地服务
由上面的例子BrowserRouter:http://localhost:8080/test/guide
,可见,使用BrowserRouter,history
对url连接进行了处理,当连接跳转以后,若是对页面进行刷新reload操做,那么本地服务
就会捕获到路由的GET请求,这就是问题的关键,须要本地服务对请求进行处理,方式有不少,这里介绍一种比较笼统直接的方式;
const router = express.Router(); const request = require("request-promise").defaults({ jar: true }); router.all("*", async (req, res, next) => { let url = req.url; //页面连接上的url let html = ""; // 不匹配如下路由规则,只匹配URL GET请求 if (url.match(/\.(png|jpe?g|gif|js|css|html|ico)/)) { return next(); } html = await reactRoute().catch(e => { //do error handle return false; }); if(html){ return res.send(html); } //其余路由处理规则... return next(); }) async function reactRoute() { return new Promise((resolve, reject) => { //这里能够作一层非react项目的过滤,这里不重要 // if(noReact){ // reject('no react url') // } let html = await request({ method: "get", url: `http://localhost:8080/pages/index.html` //本地服务index路径(为react配置的BrowserRouter路径),因项目而异,只是一个例子 }).catch(e => { reject(e); }); resolve(html); }) }
以上代码的逻辑是,本地服务,读取URL get请求,若是本地服务请求404,那么把react 的BrowserRouter 启动文件返回,该文件应该是本地服务能够读取到的html文件。
如下是图解