小工具知识网

当前位置: 首页 > 行业知识 > react 路由的基本原理及实现

行业知识

react 路由的基本原理及实现

2026-11-01 08:12:48 来源:互联网转载

1. react 路由原理

不同路���渲染不同的组件

有两种实现方式

● HasRouter 利用hash实现路由切换

● BrowserRouter 实现h5 API实现路由切换

1. 1 HasRouter

利用hash 实现路由切换

1.2 BrowserRouter

利用h5 Api实现路由的切换

1.2.1 history
  • HTML5规范给我们提供了一个history接口
  • HTML5 HIstory API包含两个方法:history.pushState()和history.replaceState(),和一个事件

    window.onpopstate pushState

    1.2.1.1 history.pushState(stateObject,title,url)

    ● 第一个参数用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可在history对象中获取

    ● 第二个参数是标题,目前浏览器并未实现

    ● 第三个参数是设定的url

    pushState函数向浏览器的历史堆栈中压入一个url为设定值的记录,并改变历史堆栈的当前指针至栈顶

    1.2.1.2 replaceState

    ● 该接口与pushState参数相同,含义 也相同

    ● 唯一的区别在于replaceState是替换浏览器历史栈中的当前历史记录为设定的url

    ● 需要注意的是replaceState 不会改动浏览器历史堆栈的当前指针

    1.2.1.3 onpopstate

    ● 该事件是window属性

    ● 该事件会在调用浏览器的前进,后退以及在执行history.forward,history.back 和history.go 的时候触发。因为这些操作有一个共性,即修改了历史堆栈的当前指针

    ● 在不改变document 的前提下,一旦触发当前指针改变则会触发onpopstate事件

    2 实现基本路由

    2.1 HashRouter 基本用法及实现

    import React from 'react';import { Router } from '../react-router';import { createHashHistory } from '../history';class HashRouter extends React.Component {    constructor(props) {        super(props);        this.history = createHashHistory(props)    }    render() {        return (            this.history}                {this.props.children}                    )    }}export default HashRouter;

    history 下的 createHashHistory.js

    /** * 工厂方法,用来返回一个历史对象 */function createHashHistory(props) {    let stack = [];//模拟一个历史条目栈,这里放的都是每一次的location    let index = -1;//模拟一个当前索引    let action = 'POP';//动作    let state;//当前状态    let listeners = [];//监听函数的数组    let currentMessage;    let userConfirm = props.getUserConfirmation?props.getUserConfirmation():window.confirm;    function go(n) {//go是在历史条目中跳前跳后,条目数不会发生改变        action = 'POP';        index += n;        if(index             index=0;        }else if(index =stack.length){            index=stack.length-1;        }        let nextLocation = stack[index];        state=nextLocation.state;        window.location.hash = nextLocation.pathname;//用新的路径名改变当前的hash值    }    function goForward() {        go(1)    }    function goBack() {        go(-1)    }    let listener = ()=>{        let pathname = window.location.hash.slice(1);// /users#/api  /api        Object.assign(history,{action,location:{pathname,state}});         if(action === 'PUSH'){          stack[++index]=history.location;//1 2 3 6 5           //stack.push(history.location);        }        listeners.forEach(listener=>listener(history.location));     }    window.addEventListener('hashchange',listener);    //to={pathname:'',state:{}}    function push(to,nextState){        action = 'PUSH';        let pathname;        if(typeof to === 'object'){            state = to.state;            pathname = to.pathname;        }else {            pathname = to;            state = nextState;        }        if(currentMessage){            let message = currentMessage({pathname});            let allow = userConfirm(message);            if(!allow) return;        }        window.location.hash = pathname;    }    function listen(listener) {        listeners.push(listener);        return function () {//取消监听函数,如果调它的放会把此监听函数从数组中删除            listeners = listeners.filter(l => l !== listener);        }    }    function block(newMessage){        currentMessage = newMessage;        return ()=>{            currentMessage=null;        }    }    const history = {        action,//对history执行的动作        push,        go,        goBack,        goForward,        listen,        location:{pathname:window.location.hash.slice(1),state:undefined},        block    }    if(window.location.hash){        action = 'PUSH';        listener();    }else{        window.location.hash='/';    }    return history;}export default createHashHistory;

    2.2 BrowserRouter基本用法及实现

    import React from 'react';import { Router } from '../react-router';import { createBrowserHistory } from '../history';class BrowserRouter extends React.Component {    constructor(props) {        super(props);        this.history = createBrowserHistory(props)    }    render() {        return (            this.history}                {this.props.children}                    )    }}export default BrowserRouter;

    history 下的 createBrowserHistory.js

    /** * 工厂方法,用来返回一个历史对象 */function createBrowserHistory(props){  let globalHistory = window.history;  let listeners = [];  let currentMessage;  let userConfirm = props.getUserConfirmation?props.getUserConfirmation():window.confirm;  function go(n){    globalHistory.go(n);  }  function goForward(){    globalHistory.goForward();  }  function goBack(){    globalHistory.goBack();  }  function listen(listener){    listeners.push(listener);    return function(){//取消监听函数,如果调它的放会把此监听函数从数组中删除        listeners = listeners.filter(l=>l!==listener);    }  }  window.addEventListener('popstate',(event)=>{//push入栈 pop类似于出栈    setState({action:'POP',location:{state:event.state,pathname:window.location.pathname}});  });  function setState(newState){    Object.assign(history,newState);    history.length = globalHistory.length;    listeners.forEach(listener=>listener(history.location));  }  /**   * push方法   * @param {*} path 跳转的路径   * @param {*} state 跳转的状态   */  function push(to,nextState){//对标history pushState     const action = 'PUSH';     let pathname;     let state;     if(typeof to === 'object'){         state = to.state;         pathname = to.pathname;     }else {         pathname = to;         state = nextState;     }     if(currentMessage){      let message = currentMessage({pathname});      let allow = userConfirm(message);      if(!allow) return;     }     globalHistory.pushState(state,null,pathname);     let location = {state,pathname};     setState({action,location});  }  function block(newMessage){    currentMessage = newMessage;    return ()=>{        currentMessage=null;    }}  const history = {    action:'POP',//对history执行的动作    push,    go,    goBack,    goForward,    listen,    location:{pathname:window.location.pathname,state:globalHistory.state},    block  }  return history;}export default createBrowserHistory;

上一篇:光泽黑用pS怎么调?

下一篇:服务器线程撕裂者怎么用?