Hash路由

hash路由一个明显的标志是带有#,我们主要是通过监听url中的hash变化来进行路由跳转。

实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Hash路由</title>
</head>

<body>
    <ul>
        <li><a href="#/">turn yellow</a></li>
        <li><a href="#/blue">turn blue</a></li>
        <li><a href="#/green">turn green</a></li>
    </ul>
    <script>
        class Routers {
            constructor() {
                this.routes = {}
                //当前路由
                this.currentUrl = ''
                this.refresh = this.refresh.bind(this)
                window.addEventListener('load', this.refresh, false)
                window.addEventListener('hashchange', this.refresh, false);
            }
            route(path, callback) {
                this.routes[path] = callback || function () {}
            }
            //刷新
            refresh() {
                this.currentUrl = location.hash.slice(1) || '/'
                //执行Callback
                this.routes[this.currentUrl]()
            }
        }
        window.Router = new Routers();
        var content = document.querySelector('body');

        function changeBgColor(color) {
            content.style.backgroundColor = color;
        }
        //定义路由
        Router.route('/', function () {
            //回调函数
            changeBgColor('yellow');
        });
        Router.route('/blue', function () {
            changeBgColor('blue');
        });
        Router.route('/green', function () {
            changeBgColor('green');
        });
    </script>
</body>

</html>

History路由

常用的API

  • window.history.back(); // 后退
  • window.history.forward(); // 前进
  • window.history.go(-3); // 后退三个页面

history.pushState

用于在浏览历史中添加历史记录,但是并不触发跳转,此方法接受三个参数,依次为:

  • state:一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null。
  • title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填null。
  • url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

history.replaceState方法的参数与pushState方法一模一样,区别是它修改浏览历史中当前纪录,而非添加记录,同样不触发跳转。popstate事件,每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。
需要注意的是,仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用back、forward、go方法时才会触发。

实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>History路由</title>
</head>

<body>
    <ul>
        <li><a href="/">turn yellow</a></li>
        <li><a href="/blue">turn blue</a></li>
        <li><a href="/green">turn green</a></li>
    </ul>
    <script>
        //常用api
        // window.history.back(); // 后退
        // window.history.forward(); // 前进
        // window.history.go(-3); // 后退三个页面
        class Routers {
            constructor() {
                this.routes = {}
                this._bindPopState()
            }
            //初始化
            init(path) {
                history.replaceState({
                    path
                }, null, path)
            }
            route(path, callback) {
                this.routes[path] = callback || function () {}
            }
            go(path) {
                history.pushState({
                    path
                }, null, path)
                this.routes[path]();
            }
            // 监听popstate事件
            _bindPopState() {
                window.addEventListener('popState', e => {
                    const path = e.state && e.state.path;
                    this.routes[path] && this.routes[path]();
                })
            }
        }
        window.Router = new Routers();
        Router.init(location.pathname);
        const content = document.querySelector('body');
        const ul = document.querySelector('ul');

        function changeBgColor(color) {
            content.style.backgroundColor = color;
        }

        Router.route('/', function () {
            changeBgColor('yellow');
        });
        Router.route('/blue', function () {
            changeBgColor('blue');
        });
        Router.route('/green', function () {
            changeBgColor('green');
        });

        ul.addEventListener('click', e => {
            if (e.target.tagName === 'A') {
                e.preventDefault();
                Router.go(e.target.getAttribute('href'));
            }
        });
    </script>
</body>

</html>