react 路由的基本原理及实现

02-29 1758阅读 0评论

1. react 路由原理

不同路径渲染不同的组件

react 路由的基本原理及实现,react 路由的基本原理及实现,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,接口,方法,修改,第1张
(图片来源网络,侵删)

有两种实现方式

● HasRouter 利用hash实现路由切换

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

1. 1 HasRouter

利用hash 实现路由切换

react 路由的基本原理及实现

1.2 BrowserRouter

利用h5 Api实现路由的切换

react 路由的基本原理及实现,react 路由的基本原理及实现,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,接口,方法,修改,第3张
(图片来源网络,侵删)
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

    react 路由的基本原理及实现,react 路由的基本原理及实现,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,接口,方法,修改,第4张
    (图片来源网络,侵删)

    ● 需要注意的是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;
    

免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1758人围观)

还没有评论,来说两句吧...

目录[+]