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

一、什么是路由?

路由是根据不同的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来实现的,一般用于不同内容的展示和切换。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值