【白说】React-router原理

108 阅读2分钟

原理介绍

最核心是实现:页面局部刷新和url变化而不跳转

从性能和用户体验的层面来比较的话,后端路由每次访问一个新页面的时候都要向服务器发送请求,然后服务器再响应请求,这个过程肯定会有延迟。而前端路由在访问一个新页面的时候仅仅是变换了一下路径而已,没有了网络延迟,对于用户体验来说会有相当大的提升。

在HTML5的historyAPI出现之前,前端的路由都是通过hash来实现的,hash能兼容低版本的浏览器。Web服务并不会解析hash,也就是说#后的内容Web服务都会自动忽略,但是JavaScript是可以通过window.location.hash读取到的,读取到路径加以解析之后就可以响应不同路径的逻辑处理。

history是HTML5才有的新API,可以用来操作浏览器的session history(会话历史)。基于history来实现的路由可以和最初的路径规则一样,即不带#。用户可能都察觉不到该访问地址是Web服务实现的路由还是前端实现的路由。

关于histroy

上面提到了,history 是html5后的新方法。

window.history.back() : 后退,类似浏览器的回退

window.history.forward():前进

window.history.go(-1): 跳到前一步

window.history.length: url的队列


这里很明显了,window.history 就是记录web浏览器的历史记录的一个堆栈


看图说话:

有三个页面,打开index.html 后,通过a标签跳转到了 page2.html,再在page2.html的a标签,跳转到了 page3.html

\

这时候的

调用window.history.back() ,指针就往下走,读取page2.html


现在明白了一般情况,那我们怎么实现页面局部刷新和url变化而不跳转?


就要用到 history.pushState 和 popstate

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <title>test router</title>
        <script type="text/javascript" src="http://s.thsi.cn/cb?js/jquery-1.9.0.js"></script>
        <link rel="stylesheet" href="" />
    </head>
    <body>
        <div>当前页面:</div>
        <div id="box">
            <a href="javascript:;" id="toindex">index</a>
            <a href="javascript:;" id="toPage2">page2</a>
            <a href="javascript:;" id="toPage3">page3</a>
        </div>
    </body>

    <script>
        // 把文字高亮为红色
        function setRed(id) {
            var links = $("#box").find("a");
            for (var i = 0; i < links.length; i++) {
                var linkId = links[i].id;

                if (linkId === id) {
                    links[i].style.color = "red";
                } else {
                    links[i].style.color = "black";
                }
            }
        }

        // 切换页面,对应的文字高亮,url改变
        $("#box").on("click", "a", function (e) {
            let currentId = $(e.currentTarget).attr("id");
            window.history.pushState(
                {
                    id: currentId,
                },
                "select " + currentId,
                "./" + currentId
            );
            setRed(currentId);
        });

    </script>
</html>

效果如下:

可以注意到现在url在改变,而页面并没有刷新。 但是我在尝试回退的时候,发现文字并没有高亮,主要是没有监听回退后的变化

代码中再加上这段即可:

       function setRed(id) {
            var links = $("#box").find("a");
            for (var i = 0; i < links.length; i++) {
                var linkId = links[i].id;

                if (linkId === id) {
                    links[i].style.color = "red";
                } else {
                    links[i].style.color = "black";
                }
            }
        }

        // 切换页面,对应的文字高亮,url改变
        $("#box").on("click", "a", function (e) {
            let currentId = $(e.currentTarget).attr("id");
            window.history.pushState(
                {
                    id: currentId,
                },
                "select " + currentId,
                "./" + currentId
            );
            setRed(currentId);
        });

        // 对于 pushState 回退的监听
        window.addEventListener('popstate', function (e) {
            setRed(e.state.id)
        })

参考资料: www.jianshu.com/p/704495262…\