模拟hash模式和history模式

在vue-router中有两种模式:hash模式和history模式

hash模式

hash模式:是用hash方式来模拟一个完整URL,其中URL中hash值即自带#之后值,
hash值发生变化时,页面不会重新加载,可以通过onhashchange事件来监听hash(window.location.hash)值的变化来实现更新页面需要更新内容,不需刷新页面。
模拟一个hash模式例子来加深理解,代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #nav a {
            margin-right: 10px;
        }

        #nav a.act {
            color: #FF0000;
        }
    </style>
</head>
<body>
    <nav id="nav"></nav>
    <main id="app"></main>
    <script>
        class Router {
            constructor() {
                this.navs = [{
                    path: "#index",
                    title: "首页",
                    content: "首页-内容"
                }, {
                    path: "#news",
                    title: "新闻",
                    content: "新闻-内容"
                }, {
                    path: "#about",
                    title: "关于",
                    content: "关于-内容"
                }]

                this.navNode = document.getElementById("nav");
                this.el = document.getElementById("app");
            }
            init() {
                this.createNav();
                this.haddleHashChage();
                //监听hash值变动
                window.addEventListener("hashchange", this.haddleHashChage.bind(this));
            }
            createNav() {//创建导航
                let fragment = document.createDocumentFragment();
                this.navs.forEach(nav => {
                    let tagA = document.createElement("a");
                    tagA.href = nav.path;
                    tagA.innerText = nav.title;
                    fragment.appendChild(tagA);
                })
                this.navNode.appendChild(fragment);
            }
            haddleHashChage() {//根据hash值,变动内容
                const hashVal = window.location.hash || this.navs[0].path;
                this.navs.forEach((nav, index) => {
                    let curNodes = this.navNode.childNodes[index];
                    curNodes.className = "";
                    if (nav.path == hashVal) {
                        curNodes.className = "act";
                        this.el.innerHTML = nav.content;
                    }
                })
            }
        }

        const router = new Router();
        router.init();
    </script>
</body>
</html>

history模式

若不想URL后面带#hash值,就可以采用history模式,
先了解historyAPI,链接: https://developer.mozilla.org/zh-CN/docs/Web/API/History_API.
history模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
是利用history.pushState(添加一条历史记录)来更改 URL 跳转而无须重新加载页面,当页面前进后退,意味着历史记录项发生变化了,就会onpopstate事件,监听页面需要更新内容,不需刷新页面。
模拟一个history模式例子来加深理解,代码如下

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #nav a {
            margin-right: 10px;
        }

        #nav a.act {
            color: #FF0000;
        }
    </style>
</head>

<body>
    <nav id="nav"></nav>
    <main id="app"></main>
    <script>
        class Router {
            constructor() {
                this.navs = [{
                    path: "?page=index",
                    title: "首页",
                    content: "首页-内容"
                }, {
                    path: "?page=news",
                    title: "新闻",
                    content: "新闻-内容"
                }, {
                    path: "?page=about",
                    title: "关于",
                    content: "关于-内容"
                }];

                this.navNode = document.getElementById("nav");
                this.el = document.getElementById("app");
                this.curPage = "";
            }
            init() {
                this.createNav();
                this.haddleNav();
                this.haddlePopstate();
                window.addEventListener("popstate", this.haddlePopstate.bind(this))
            }
            createNav() {//创建导航
                let fragment = document.createDocumentFragment();
                this.navs.forEach(nav => {
                    let tagA = document.createElement("a");
                    tagA.href = nav.path;
                    tagA.setAttribute("data-page", nav.path);
                    tagA.innerText = nav.title;
                    fragment.appendChild(tagA);
                })
                this.navNode.appendChild(fragment);
            }
            haddleNav() {//点击导航
                this.navNode.addEventListener("click", function (evt) {
                    evt.preventDefault();
                    let target = evt.target;
                    if (target.nodeName == "A") {
                        this.curPage = target.getAttribute("data-page");
                        history.pushState("", "", this.curPage)
                        this.navToContent();
                    }
                }.bind(this))
            }
            navToContent() {//切换内容
                this.navs.forEach((nav, index) => {
                    let curNodes = this.navNode.childNodes[index];
                    curNodes.className = "";
                    if (nav.path == this.curPage) {
                        curNodes.className = "act";
                        this.el.innerHTML = nav.content;
                    }
                })
            }
            haddlePopstate() {//查询参数发生变化时
                this.curPage = this.queryParams();
                this.navToContent();
            }
            queryParams() {//查询参数
                return window.location.search || this.navs[0].path;
            }
        }

        const router = new Router();
        router.init();
    </script>
</body>

</html>

以上两个例子也在我的github上查看
链接: https://github.com/mina882/hash-pushState.

猜你喜欢

转载自blog.csdn.net/qq_31093255/article/details/107509141
今日推荐