React路由系列-初始路由

2,461 阅读2分钟

这是我参与更文挑战的第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#…

image.png

image.png

2.2 在谷歌浏览器打开localhost说明环境安装好了

image.png

2.3 指定另外服务路径

修改这个文件

image.png image.png

2.4 改完后重启服务器

image.png

2.5 配置成功

image.png 以后你的每一个目录就是一个网站

image.png

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>

2021-06-19-18-45-17.gif

三、看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 路由

image.png

history 路由

 <BrowserRouter>
    <React.Fragment>
        <Route path={'/'} component={IndexPage}></Route>
    </React.Fragment>
</BrowserRouter>

image.png

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

效果

2021-06-19-19-22-00.gif

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

2021-06-19-19-37-30.gif

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))

2021-06-19-20-13-11.gif

简化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>

效果

2021-06-19-20-33-48.gif