前端路由也能像vue-router一样香

9/14/2022 前端路由

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情 (opens new window)

vue-router路由用着是不是香香的?简单易上手。其实,前端路由也是简单易上手哦,一起来学学趴~。

# 一、先看看vue-router的效果

Video_Vue.gif

# 二、什么是前端路由

前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做,之前是通过服务端根据 url 不同返回不同的页面来实现。

前端路由描述的是URL和UI之间的映射关系,单向映射。

# 三、前端路由解决的两个主要问题

1、如何检测URL发生了变化

2、如何改变URL却不引起页面的刷新(例如,变成hash的改变)

# 四、实现前端路由的方案

# 1、hash模式

什么是hash?hash模式是基于锚点的原理实现。在 location 对象属性中,location .hash 是设置或返回从井号(#)开始的URL(锚)。使用hash模式一定有一个#,并且通过这个模式,改变url中的hash值部分,页面是不会刷新的,这就解决了第一个主要问题。

# 看看demo:

    <body>
        <ul>
            <!-- hash模式如何改变URL?在路径面前添加#,这里展示的是三个不同的URL -->
            <li><a href="#/home">首页</a></li>
            <li><a href="#/about">关于</a></li>
            <li><a href="#/mine">我的</a></li>
        </ul>
​
        <!-- 准备一个容器,渲染对应的UI,相当于vue-router里面的<router-view></router-view> -->
        <div id="routerView"></div>
​
        <script>
            let routerView = document.getElementById('routerView');
            // 页面加载完毕(强制匹配一次)
            window.addEventListener('load', onHashchange);
            // 监听hash改变
            window.addEventListener('hashchange', onHashchange);
​
            // 控制渲染对应的UI
            function onHashchange() {
                console.log(location.hash);
                //设置不同路由对应不同的内容
                switch (location.hash) {
                    case '#/home':
                        routerView.innerHTML = "Home"
                        return
                    case '#/about':
                        routerView.innerHTML = "About"
                        return
                    case '#/mine':
                        routerView.innerHTML = "Mine"
                        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
32
33
34
35
36
37
38

# 实现效果长这样:

hash_vedio (1).gif

# hash 模式适用场景:

无重定向传参需求(第三方认证 oauth) ,兼容IE8,无锚点跳跃需求,后端不需要跟踪前端路由信息。

# 优缺点分析:

(1)优点:实现简单,兼容性好,绝大多数前端框架提供了 hash 的路由实现,不需要服务器端进行任何设置和开。除资源加载和 ajax 请求外,不发起其他请求。

(2)缺点:需要重定向的操作,后端无法获取 hash 部分内容,也就是后台无法取得url中的数据。换句话说,服务器端无法准确跟踪前端路由信息,对于需要锚点功能的需求会与目前路由机制冲突。

# 2、history模式

HTML5提供的一个对象方法,

修改url,是不会引起页面刷新的 :

(1)pushState() (文章使用这个)

(2)replaceState()

检测url变化 :

(3)popState()

# 看看demo:

    <body>
        <ul>
            <!-- history模式如何改变URL?直接写,不需要# -->
            <li><a href="/home">首页</a></li>
            <li><a href="/about">关于</a></li>
            <li><a href="/mine">我的</a></li>
        </ul>
​
        <!-- 准备一个容器,渲染对应的UI,相当于vue-router里面的<router-view></router-view> -->
        <div id="routerView"></div>
​
        <script>
            let routerView = document.getElementById('routerView');
            window.addEventListener('DOMContentLoaded', onLoad);
            window.addEventListener('popstate', onPopState); //浏览器前进后退内容与路由能够匹配
​
            function onLoad() {
                onPopState()
                let links = document.querySelectorAll('li a[href]');
                // 拦截a标签的默认跳转行为
                links.forEach(a => {
                    a.addEventListener('click', (e) => {
                    // e.stopImmediatePropagation()  
                    //阻止剩下的事件处理程序执行。会阻止冒泡。停止当前节点和所有后续节点的事件处理程序的运行。
                    // e.stopPropagation() 
                    //阻止事件向上层元素冒泡。若同一个元素绑定多个事件(如addEventListener),则不阻止其他事件的执行
                        
                        // 阻止a标签href的默认行为
                        e.preventDefault();
                        console.log(123);
                        history.pushState(null, '', a.getAttribute('href'));
                        onPopState()
                    })
                })
​
            }
​
            function onPopState() {
                console.log(location);
                switch (location.pathname) {
                    case '/home':
                        routerView.innerHTML = 'Home'
                        return
                    case '/about':
                        routerView.innerHTML = 'about'
                        return
                    case '/mine':
                        routerView.innerHTML = 'mine'
                        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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 实现效果长这样:

history.gif

# history 模式适用场景:

页面锚点需求,需重定向传参,后端跟踪路由信息,附加路由信息(history.state)获取路由状态。

# 优缺点分析:

(1)优点:重定向过程中不会丢失url参数。后端可以拿到数据。绝大多数前段框架提供了 history 模式的路由实现。后端可准确跟踪路由信息,history.state 可获取当前 url 对应的状态信息。

(2)缺点:兼容性只兼容到 IE10, 需要后端支持。

Last Updated: 12/18/2022, 5:18:06 PM
Faster Than Light
Andreas Waldetoft / Mia Stegmar