vue-router的两种路由模式[Hash 模式和History(Html5)模式]

4/1/2024 Vue

# 简单介绍

官网介绍 (opens new window)

  • Hash 模式 通过createWebHashHistory创建,URL 中会有一个哈希字符(#),hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端没影响,改变 hash 不会重新加载页面。

  • HTML5 模式 通过createWebHistory创建,URL 看起来比较正常,需要 nginx 配置支持才能正常访问。

# 模拟实现

<body>
    <ul>
        <!-- 定义路由 hash模式-->
        <h3>Hash Router</h3>
        <li><a href="#/home">home</a></li>
        <li><a href="#/about">about</a></li>
    </ul>
    <!-- 渲染路由对应的UI -->
    <div id="routeView"></div>
    <script>
        window.addEventListener('DOMContentLoaded', onLoad)
        window.addEventListener('hashchange', onHashChange)
        var routerView = null
        function onLoad() {
            routerView = document.querySelector('#routeView')
            onHashChange()
        }
        function onHashChange() {
            switch (location.hash) {
                case '#/home':
                    routerView.innerHTML = 'Home'
                    return
                case '#/about':
                    routerView.innerHTML = 'About'
                    return
                default:
                    return
            }
        }
    </script>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<body>
    <h3>history模式 Router</h3>
    <ul>
        <li><a href="/home">home</a></li>
        <li><a href="/about">about</a></li>
        <div id="routeView"></div>
    </ul>
</body>
<script>
    // 该模式不能跨域,出现跨域,会提示
    // Uncaught DOMException: Failed to execute 'pushState' on 'History': A history state object with URL
    // 可通过http-server启动一个服务
    window.addEventListener('DOMContentLoaded', onLoad)
    window.addEventListener('propstate', onPropState)
    let routeView = null
    function onLoad() {
        routerView = document.querySelector('#routeView')
        // 拦截a标签默认点击行为
        const linkList = document.querySelectorAll('a[href]')
        linkList.forEach((el) => {
            el.addEventListener('click', function (e) {
                e.preventDefault()
                history.pushState(null, '', el.getAttribute('href'))
                onPropState()
            })
        })
    }

    // 路由变化时,根据路由渲染对应ui
    function onPropState() {
        switch (location.pathname) {
            case '/home':
                routerView.innerHTML = 'home'
                break
            case '/about':
                routerView.innerHTML = 'about'
                break
        }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 遇到的问题

飞书扫码确认之后,内部处理之后会在 URL 上携带 Code。但两种模式携带 code 的位置不一样。 Hash 模式原来的 url 为https://XXX.com:23181/#/login,携带 code 的链接为https://XXX.com:23181/?code=XXXX&state=success_login#/login,通过 router.query 获取不到。

History 模式原来的 url 为https://XXX.com:23181/login,携带 code 的链接为https://XXX.com:23181/login?code=XXXX&state=success_login,通过 router.query 可以获取到。 但是都可以通过location.search获取到,通过以下方式解析获取到。

const params = new URLSearchParams(location.search)
const [code] = [params.get('code')]
1
2

如图所示,所以有个大胆猜测,飞书扫码重定向处理 URL 是不是通过url.searchParams.set方式添加上 code 参数的。

如图所示

code 获取到了,又遇到新的问题了,Hash 模式通过router.push跳转页面时候,search 参数不会清空,详情如图,注意看路由变化。

路由

那么如何清空 sarch 参数呢,我目前处理方法是通过正则给清空掉,各位大佬们还有什么更好的处理方式吗,欢迎指点。

const newUrl = url.replace(/\?code=[a-z0-9]+&state=success_login/, '')
history.replaceState({}, document.title, newUrl)
1
2
上次更新: 4/2/2024, 9:59:45 AM