欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端路由hash、history模式的区别及简单实现

程序员文章站 2022-03-25 09:52:25
...

一、什么是路由?

路由是根据不同的url地址来显示不同的页面或内容。
当我们访问一个url地址的时候,大致流程可以想象成这样:

  1. 浏览器向服务器发出请求;
  2. 服务器监听到80端口,如果有请求,那么就解析url地址。
  3. 服务器根据路由配置,然后就返回相应的信息(比如html字符串、json数据或图片等)。
  4. 浏览器根据服务器响应的Content-Type来决定如何解析数据。

以上就是传统路由最初始的实现方式,缺点是每次路由切换都需要刷新页面,发ajax请求,然后把数据返回回来,这样对用户体验就不好了
因此为了提升用户体验,前端路由就产生了,它就可以解决浏览器不会重新刷新了。

在了解路由之前,先简单的看一下history api有哪些方法:

> window.history.length: 返回当前会话浏览的页面数量;
> window.history.go(): 接收一个整数作为参数,按照当前页面在会话浏览历史记录中的位置进行移动;
> window.history.back(): 移动到上一页。相当于点击浏览器的后退按钮;
> window.history.forward(): 移动到下一页,相当于点击浏览器的前进按钮;
> window.history.pushState(): 在会话浏览历史记录中添加一条记录;
> window.history.replaceState(): 该方法用法和history.pushState方法类似,但是该方法的含义是将修改会话浏览历史的当前记录,而不是新增一条记录。

有了这些基本知识后,我们再来看下前端路由,前端路由也有2种模式,第一种是hash模式,第二种是history模式。我们来分别看下这两种知识点及区别如下:

二、hash模式

hash路由模式是这样的:http://xxx.com/#/xx。 带#号,后面就是hash值的变化。实现hash路由的基本条件:

  1. url中hash值的改变,并不会重新加载页面;
  2. hash值的改变会在浏览器的访问历史中增加一条记录,可以通过浏览器的后退,前进按钮控制hash值的切换;
  3. 可以通过hashchange事件,监听到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 test</title>
</head>
<body>
    <p>hash test</p>
    <button id="btn">修改 hash</button>

    <script>
        // hash 变化,包括:
        // a. JS 修改 url
        // b. 手动修改 url 的 hash
        // c. 浏览器前进、后退
        window.onhashchange = (event) => {
            console.log('old url', event.oldURL)
            console.log('new url', event.newURL)
            console.log('hash:', location.hash)
        }

        // 页面初次加载,获取 hash
		// 当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发
        document.addEventListener('DOMContentLoaded', () => {
            console.log('hash:', location.hash)
        })

        // JS 修改 url
        document.getElementById('btn').addEventListener('click', () => {
            location.href = '#/user'
        })
    </script>
</body>
</html>

三、history模式

  • 用url规范的路由,但跳转时不刷新页面;
  • window.history.pushState 能修改路径、查询参数和片段标识符。pushState比hash更符合前端路由的访问方式,更加优雅(因为不带#号);
  • window.onpopstate来监听历史栈的改变,只要历史栈有信息发生改变的话,就会触发该事件。

示例:

<!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 API test</title>
</head>
<body>
    <p>history API test</p>
    <button id="btn">修改 url</button>

    <script>
        // 页面初次加载,获取 path
        document.addEventListener('DOMContentLoaded', () => {
            console.log('load', location.pathname)
        })

        // 打开一个新的路由
        // 【注意】用 pushState 方式,浏览器不会刷新页面
        document.getElementById('btn').addEventListener('click', () => {
            const state = { name: 'page1' }
            console.log('切换路由到', 'page1')
            history.pushState(state, '', 'page1') // 重要!!!
        })

        // 监听浏览器前进、后退
        window.onpopstate = (event) => { // 重要!!!
            console.log('onpopstate', event.state, location.pathname)
        }
    </script>
</body>
</html>

需要 server 端配合,可参考
https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90

四、总结

传统的路由指的是:当用户访问一个url时,对应的服务器会接收这个请求,然后解析url中的路径,从而执行对应的处理逻辑。这样就完成了一次路由分发。

而前端路由是不涉及服务器的,是前端利用hash或者HTML5的history API来实现的,一般用于不同内容的展示和切换。