这是我参与更文挑战的第17天,活动详情查看: 更文挑战
一、React Route介绍
使用React构建的单页面应用,使用路由实现页面跳转。在React中,常用的两个包可以实现这些需求,那就是React-router和React-router-dom(router V4)
react-router实现了路由的核心功能
react-router-dom: 基于react-router, 加入了再浏览器运行环境的一些功能, 例如: Link组件, 会渲染一个a标签, 路由模式分为: BrowserRouter(history)(不带#号)和HashRouter(带#号), 前者使用pushState和popState事件构建路由, 后者使用window.localtion.hash和hashchange事件构建路由。
二、手写路由
2.1 H5环境准备
安装Apache,这里使用的是wampserver php集成工具 百度网盘地址:pan.baidu.com/s/1dGYXDa5#…
2.2 在谷歌浏览器打开localhost说明环境安装好了
2.3 指定另外服务路径
修改这个文件
2.4 改完后重启服务器
2.5 配置成功
以后你的每一个目录就是一个网站
2.6 新建一个html,模拟路由
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>路由原理</title>
</head>
<body>
<button type="button" onclick="history.go(-1)">返回</button><br/>
push模式
<ul>
<li onclick="Router.push(baseUrl)">首页</li>
<li onclick="Router.push(baseUrl+'news')">新闻</li>
<li onclick="Router.push(baseUrl+'product')">产品</li>
</ul>
replace模式
<ul>
<li onclick="Router.replace(baseUrl)">首页</li>
<li onclick="Router.replace(baseUrl+'news')">新闻</li>
<li onclick="Router.replace(baseUrl+'product')">产品</li>
</ul>
<div id="app"></div>
<script>
var app=document.getElementById("app"),baseUrl="/router/";
function RouterClass(opts){
this.routes={};
this.curUrl="";
this.mode="";
if(opts){
this.mode=opts.mode;
if(this.mode==='history'){
this.eventHistoryRouter();
}else{
this.eventHashRouter();
}
}else {
this.eventHashRouter();
}
}
RouterClass.prototype.route=function(path,callback){
this.routes[path]=callback || function(){}
};
//hash模式
RouterClass.prototype.hashRouter=function(){
this.curUrl=window.location.hash.slice(1) || '/';
this.routes[this.curUrl]();
};
//监听hash模式路由
RouterClass.prototype.eventHashRouter=function(){
window.addEventListener("load",this.hashRouter.bind(this));
window.addEventListener("hashchange",this.hashRouter.bind(this));
};
//history模式
RouterClass.prototype.historyRouter=function(){
this.curUrl=window.location.pathname;
this.routes[this.curUrl]();
};
//监听history模式路由
RouterClass.prototype.eventHistoryRouter=function(){
window.addEventListener("load",this.historyRouter.bind(this));
window.addEventListener("popstate",this.historyRouter.bind(this));
};
//push模式跳转页面
RouterClass.prototype.push=function(url){
if(this.mode==='history'){
window.history.pushState({},null,url);
this.routes[url]();
}else {
url="#"+url;
window.location.href = url;
}
};
//replace模式跳转页面
RouterClass.prototype.replace=function(url){
if(this.mode==='history'){
window.history.replaceState({},null,url);
this.routes[url]();
}else {
url = "#" + url;
window.location.replace(url);
}
};
var Router=new RouterClass({
mode:"history" //hash:带#号,history:不带#号
});
Router.route(baseUrl,function(){
app.innerHTML="首页"
})
Router.route(baseUrl+'news',function(){
app.innerHTML="新闻页面"
})
Router.route(baseUrl+'product',function(){
app.innerHTML="产品页面"
})
</script>
</body>
</html>
三、看react中的router
3.1 安装react-router-dom
npm i --save-dev react-router-dom
3.2
import React from 'react';
import {HashRouter,Route} from 'react-router-dom'
import IndexPage from './pages/index'
class Router extends React.Component{
constructor(){
super();
this.state={
};
}
componentDidMount(){
}
render(){
return (
<React.Fragment>
<HashRouter>
<React.Fragment>
<Route path={'/'} component={IndexPage}></Route>
</React.Fragment>
</HashRouter>
</React.Fragment>
)
}
}
export default Router;
hash 路由
history 路由
<BrowserRouter>
<React.Fragment>
<Route path={'/'} component={IndexPage}></Route>
</React.Fragment>
</BrowserRouter>
3.2 Link to就可以页面跳转
首页
import React from 'react'
import {Link} from 'react-router-dom'
class Index extends React.Component {
render() {
return (
<React.Fragment>
<div>首页</div>
<Link to={'/news'}>
<button>
去新闻页
</button>
</Link>
</React.Fragment>
)
}
}
export default Index
新闻页
import React from 'react'
import {Link} from 'react-router-dom'
class Index extends React.Component {
render() {
return (
<React.Fragment>
<div>新闻</div>
<Link to={'/'}>
<button>回首页</button>
</Link>
</React.Fragment>
)
}
}
export default Index
效果
3.3 restful 风格带参
router.js中
<Route path={'/news/detail/:id/:title'} exact component={NewsDetailPage}></Route>
列表页
import React from 'react'
import {Link} from 'react-router-dom'
class Index extends React.Component {
render() {
return (
<React.Fragment>
<div>新闻</div>
<ul>
<li><Link to={'/news/detail/110/火山爆发'}>新闻一</Link></li>
<li><Link to={'/news/detail/120/冰雪消融'}>新闻二</Link></li>
</ul>
<Link to={'/'}>
<button>回首页</button>
</Link>
</React.Fragment>
)
}
}
export default Index
详情页
import React from 'react'
import {Link} from 'react-router-dom'
class Index extends React.Component {
componentDidMount() {
console.log(this.props,'参数信息')
}
render() {
return (
<React.Fragment>
<div>新闻详情页面</div>
</React.Fragment>
)
}
}
export default Index
3.3 不确定多少参数用this.props.history.push跳转
<li onClick={()=>{
this.props.history.push({
pathname: '/news/detail',
search:'id=119&title=太阳耀光',
query: {
id: 119,
title: '太阳耀光'
}
})
}}>新闻三</li>
ps: 为了防止query刷新参数丢失, 用search传, 然后自己封装一个方法转search字符串, 为一个对象的形式 utils.js
export function localParam (search, hash) {
search = search || window.location.search;
hash = hash || window.location.hash;
var fn = function(str, reg) {
if (str) {
var data = {};
str.replace(reg, function($0, $1, $2, $3) {
data[$1] = $3;
});
return data;
}
};
return {
search : fn(search, new RegExp("([^?=&]+)(=([^&]*))?", "g")) || {},
hash : fn(hash, new RegExp("([^#=&]+)(=([^&]*))?", "g")) || {}
};
}
import {localParam} from '../../assets/js/utils/index'
console.log(this.props,'参数信息')
console.log(localParam(this.props.location.search))
简化push
<li onClick={()=>{
this.props.history.push('/news/detail?id=114&title=毛里求斯')
}}>新闻四</li>
使用工具
<React.Fragment>
<div>新闻详情页面</div>
<div>
{`ID: ${routeParams.id} Title: ${decodeURIComponent(routeParams.title)}`}
</div>
<button onClick={this.props.router.goBack.bind(this)}>返回列表页</button>
</React.Fragment>