纯前端路由实现

计算机网络中,路由器是指工作在网络层,转发IP数据包的一种设备。

web服务器端编程中,用户浏览器请求一个URL,服务器根据这个URL返回对应的页面。这种请求URL和返回内容的对应关系,通常配置在一个文件里,管理这些配置的应用程序组件叫“路由器”。

后来人们提出了前后端分离、SPA应用这些概念,为了保持和原来一致的用户体验,我们可以使用JavaScript在浏览器前端模拟一个“路由器”,根据不同的URL,在界面上加载不同的组件树(更底层的理解就是DOM树)。

用URL中的"#"实现路由

SPA前端路由通常是如下这种形式。

http://www.gacfox.com/index.html#/path1

井号本来是用作页面上的锚点,URL中出现井号有一个特点,井号后面的内容改变不会触发页面重新加载,但是会触发hashchange事件,前端路由就是据此实现的(和jsonp之类的技术一样,属于有点hack的写法,代码难看且难以理解,但没办法,这属于历史遗留问题)。

下面例子中编写了一个前端“路由器”,虽然并没有实际操作组件树,只是换了一下<div>的颜色,不过思路是一致的,这里就不文字解释了,解释起来也比较曲折,直接上代码。

<body>

<div id="app" style="width: 100px; height: 100px; background: red;"></div>

<a href="#/path1">red</a>
<a href="#/path2">blue</a>
<a href="#/path3">green</a>

<script>
    class Router
    {
        constructor()
        {
            this.routes = {};
        }
        //将hashchange事件绑定到refresh()函数上
        init()
        {
            window.addEventListener("hashchange", this.refresh.bind(this), false);
        }
        //注册路由和对应的回调函数
        registerRoute(path, callback)
        {
            this.routes[path] = callback || function () {};
        }
        //读取当前的hash路径,根据已注册的路由和回调函数,更新页面
        refresh()
        {
            let currentURL = location.hash.slice(1);
            this.routes[currentURL]();
        }
    }

    function changeElementColor(element, color)
    {
        element.style.backgroundColor = color;
    }

    window.onload = function ()
    {
        let div = document.querySelector("#app");

        window.router = new Router();
        window.router.init();

        window.router.registerRoute("/path1", function ()
        {
            changeElementColor(div, "red");
        });
        window.router.registerRoute("/path2", function ()
        {
            changeElementColor(div, "blue");
        });
        window.router.registerRoute("/path3", function ()
        {
            changeElementColor(div, "green");
        });
    };
</script>
</body>

用HTML5的HistoryAPI实现路由

具体见HTML5相关章节。这个方法有个缺点,用户使用浏览器的前进后退功能,浏览器会向服务器发起新的请求,服务器需要据此进行配置,还不如上面用井号方便。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap