19-路由

6/3/2022

# 1, 认识前端路由

# 1.1, 前端路由介绍

路由其实是网络工程中的一个术语

  • 在架构一个网络时,非常重要的两个设备就是路由器和交换机
  • 目前在我们生活中路由器也是越来越被大家所熟知,因为我们生活中都会用到路由器
  • 路由器主要维护的是一个映射表,映射表会决定数据的流向

前端路由的实现方案(前端路由是如何做到URL和内容进行映射呢?监听URL的改变)

  • 前端路由的核心是什么呢?改变URL,但是页面不进行整体的刷新
  • URL的hash
  • HTML5的History

URL的hash

  • URL的hash也就是锚点(#), 本质上是改变window.location的href属性
  • 我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新
  • hash的优势就是兼容性更好,在老版IE中都可以运行,但是缺陷是有一个#,显得不像一个真实的路径
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <a href="#/home">home</a>
        <a href="#/about">about</a>
        <div class="router-view"></div>
    </div>

    <script>
        // 1,获取router-view
        const routerViewEl = document.querySelector(".router-view");
        // 2, 监听hashchange
        window.addEventListener("hashchange", () => {
            switch (location.hash) {
                case "#/home":
                    routerViewEl.innerHTML = "home";
                    break;
                case "#/about":
                    routerViewEl.innerHTML = "about";
                    break;
                default:
                    routerViewEl.innerHTML = "default";
            }
        })
    </script>
</body>

</html>
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

HTML5的History(history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面)

  • replaceState:替换原来的路径
  • pushState:使用新的路径
  • popState:路径的回退
  • go:向前或向后改变路径
  • forward:向前改变路径
  • back:向后改变路径
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title></title>
</head>
<style>
    * {
        /* global font */
        font-family: Verdana;
        font-size: 18px;
    }

    #root {
        display: flex;
        flex-direction: row;
    }

    #content {
        display: flex;
        display: block;
        width: 800px;
        height: 250px;
        /* vertically centered text */
        line-height: 250px;
        border: 2px solid #555;
        margin: 32px;
        text-align: center;
    }

    .route {
        cursor: pointer;
        justify-content: center;
        width: 150px;
        height: 50px;
        /* vertically centered text */
        line-height: 50px;
        position: relative;
        border: 2px solid #555;
        background: white;
        text-align: center;
        margin: 16px;
    }

    .route.selected {
        background: yellow;
    }
</style>

<body>
    <section id="root">
        <section class="route" id="home">/home</section>
        <section class="route" id="about">/about</section>
        <section class="route" id="gallery">/gallery</section>
        <section class="route" id="contact">/contact</section>
        <section class="route" id="help">/help</section>
    </section>
    <main id="content">Content loading...</main>
</body>
<script type="text/javascript">
    window.onload = event => {
        //监听 路由的点击事件  执行push方法
        window["home"].addEventListener("click", event => push(event))
        window["about"].addEventListener("click", event => push(event))
        window["gallery"].addEventListener("click", event => push(event))
        window["contact"].addEventListener("click", event => push(event))
        window["help"].addEventListener("click", event => push(event))
    }

    function select_tab(id) {
        // 改变 路由按钮的样式
        document.querySelectorAll(".route").forEach(item => item.classList.remove('selected'));
        document.querySelectorAll("#" + id).forEach(item => item.classList.add('selected'));
    }

    function load_content(id) {
        //更新内容
        document.querySelector("#content").innerHTML = 'Content loading for /' + id + '...';
    }

    function push(event) {
        let id = event.target.id;
        select_tab(id);
        document.title = id;
        load_content(id);
        window.history.pushState({
            id
        }, `${id}`, `/page/${id}`);
    }
    window.addEventListener("popstate", event => {
        let stateId = event.state.id;
        select_tab(stateId);
        load_content(stateId);
    });
</script>

</html>
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

# 2, 认识vue-router

# 2.1, vue-router介绍

目前前端流行的三大框架, 都有自己的路由实现

  • Angular的ngRouter
  • React的ReactRouter
  • Vue的vue-router

Vue Router 是 Vue.js 的官方路由

  • 它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用(SPA)变得非常容易
  • 路由用于设定访问路径, 将路径和组件映射起来
  • 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换
  • 安装Vue Router:npm install vue-router@3.5.3

路由的使用步骤

  • 第一步:创建路由需要映射的组件(打算显示的页面)
  • 第二步:通过new VueRouter创建路由对象,并且传入routes和history模式
    • 安装插件 Vue.use(VueRouter);
    • 配置路由映射: 组件和路径映射关系的routes数组
    • 创建基于hash或者history的模式
  • 第三步:通过 router 配置参数注入路由,从而让整个应用都有路由功能
  • 第四步:路由使用: 通过router-link和router-view
// router/index.js

//配置路由
//引入vue-router插件:经过打印查看,引入进来的VueRouter构造函数
//vue基础学习构造函数:Vue、VueComponent、Vuex.Store、VueRouter
import VueRouter from 'vue-router';
import Vue from 'vue';
//安装插件
Vue.use(VueRouter);
//引入路由组件
import Home from '../pages/Home';
import About from '../pages/About';

//配置项目的路由
//通过VueRouter【路由器】类,创建了一个VueRouter类的一个实例!!!
//对外暴露
export default new VueRouter({
    mode: 'history',
    routes: [{
    // path配置的是根路径: /
    path: "/",
    // redirect是重定向, 也就是我们将根路径重定向到/home的路径下, 这样就可以得到我们想要的结果了
    redirect: "/home"
}, {
    //path设置路由的K,path有的属性值务必都是小写的
    path: "/home",
    //component设置路由的V,一个K对应一个V
    component: Home,
}, {
    path: '/about',
    component: About
},
    ]
});
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
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from "./routes/router"

// 把路由对象挂载到根实例上
// 那么它的子子孙孙都可以使用这个路由对象
new Vue({
    router,
    render: h => h(App),
}).$mount('#app')
1
2
3
4
5
6
7
8
9
10
11
// Home.vue
<template>
  <div>
    <h1>Home组件</h1>
  </div>
</template>

<script>
export default {
  name: "Home",
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// About.vue
<template>
  <div>
      <h1>About组件</h1>
  </div>
</template>

<script>
export default {
  name:"About"
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.vue
<template>
  <div id="app">
    <!-- router-link 当成a标签 -->
    <router-link to="/home" active-class="active">Home</router-link> &nbsp;&nbsp;
    <router-link to="/about" active-class="active">About</router-link>
    <hr>
    <!-- 路由的出口:路由匹配到的组件,需要放到路由出口 -->
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
};
</script>

<style lang="less">
.active{
  color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 3, router-link

# 3.1, router-link属性

router-link属性

  • to属性: 是一个字符串,或者是一个对象
  • replace属性:设置 replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push();
  • active-class属性:设置激活a元素后应用的class,默认是router-link-active
  • exact属性:精确匹配模式

# 4, 路由懒加载

# 4.1, 路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载:

  • 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效
  • 也可以提高首屏的渲染效率
  • Vue Router默认就支持动态来导入组件
  • 因为component可以传入一个组件,也可以接收一个函数,该函数需要放回一个Promise,而import函数就是返回一个Promise
  • 分包是没有一个很明确的名称的,其实webpack从3.x开始支持对分包进行命名(chunk name)
{
    path: "/",
    redirect: "/home"
}, {
    path: "/home",
    component: ()=>import(/* webpackChunkName: "home" */"../pages/Home.vue"),
}, {
    path: '/about',
    component: ()=>import(/* webpackChunkName: "about" */"../pages/About.vue"),
},
1
2
3
4
5
6
7
8
9
10

打包后的代码如下:

# 5, 路由其他属性

# 5.1, 路由其他属性

  • name属性:路由记录独一无二的名称;
  • meta属性:自定义的数据
{
    path: "/",
    redirect: "/home"
}, {
    path: "/home",
    component: ()=>import(/* webpackChunkName: "home" */"../pages/Home.vue"),
    name:"home"
}, {
    path: '/about',
    component: ()=>import(/* webpackChunkName: "about" */"../pages/About.vue"),
    name:"about",
    meta:{
        name:"wc",
        age:18
    }
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 6, 嵌套路由和404组件

# 6.1, 嵌套路由

什么是路由的嵌套呢?

  • 我们匹配的Home、About等都属于第一级路由,我们在它们之间可以来回进行切换
  • Home页面本身,也可能会在多个组件之间来回切换
    • 比如Home中包括Cart、Mine,它们可以在Home内部来回切换
    • 这个时候我们就需要使用嵌套路由,在Home中也使用 router-view 来占位之后需要渲染的组件

404组件

  • 对于哪些没有匹配到的路由,我们通常会匹配到固定的某个页面
  • 在路由规则最后面配置:{ path:"*", component:NotFount },
import Vue from "vue";
import VueRouter from "vue-router"

// 自定义的组件  直接引入  下面的组件,一上来,就全部引入
import Home from "../components/Home"
// import About from "../components/About"
import NotFount from "../components/NotFount"
import Cart from "../components/Cart"
// import Mine from "../components/Mine"

// 能不能点击某个连接时,用到了这个组件,再去引入呢?
// 答:可以,使用路由的懒加载


Vue.use(VueRouter);

// 配置路由规则
let routes = [
    { path:"/", redirect:"/home" },
    { 
        path:"/home", 
        component:Home,
        children:[
            { path:"/home", redirect:"/home/cart" },
            { path:"/home/cart", component:Cart },
            { path:"/home/mine", component:()=>import(/* webpackChunkName: "Mine" */"../components/Mine") },
        ]
    },
    // { path:"/about", component:About },
    { path:"/about", component:()=>import(/* webpackChunkName: "About" */"../components/About") },
    { path:"*", component:NotFount },
];

let router = new VueRouter({
    // hash路由有一个特点,就是#
    mode:"hash", // hash路由
    routes
})

export default router;
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
// Home.vue
<template>
  <div>
    <h1>Home组件</h1>
    <router-link to="/home/cart">购物车</router-link>  &nbsp;&nbsp;
    <router-link to="/home/mine">我的</router-link>
    <hr>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "Home",
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// About.vue
<template>
  <div>
      <h1>About组件</h1>
  </div>
</template>

<script>
export default {
  name:"About"
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Cart.vue
<template>
  <div>
      <h3>购物车</h3>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Mine.vue
<template>
  <div>
      <h3>我的</h3>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// NotFount.vue
<template>
  <div>
      <h3>你的页面飞了</h3>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.vue
<template>
  <div id="app">
    <!-- router-link 当成a标签 -->
    <router-link to="/home" active-class="active">Home</router-link> &nbsp;&nbsp;
    <router-link to="/about" active-class="active">About</router-link>
    <hr>
    <!-- 路由的出口:路由匹配到的组件,需要放到路由出口 -->
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return{
    }
  },
  methods:{
  
  },
  components: {
  },
};
</script>

<style lang="less">
.active{
  color: red;
}
</style>
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

# 7, 动态路由

# 7.1, 动态路由基本匹配

很多时候我们需要将给定匹配模式的路由映射到同一个组件

  • 例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但是用户的ID是不同的;
  • 在Vue Router中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数;

获取动态路由的值

  • 在template中,直接通过 $route.params获取值
  • 在created中,通过 this.$route.params获取值
import VueRouter from "vue-router";
import Vue from "vue";

import Home from "../components/Home"
import About from "../components/About"
import Mine from "../components/Mine"
import NotFount from "../components/NotFount"

Vue.use(VueRouter);

let routes = [
    { path:"/", redirect:"/home" },
    { path:"/home", component:Home },
    { path:"/about", component:About },
    { path:"/mine/:name/:age/:address", component:Mine },
    { path:"*", component:NotFount },
];

let router = new VueRouter({
    // hash带#    
    // history不带#
    mode:"history",
    routes
})

export default router;
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
// Home.vue
<template>
  <div>
      <h2>Home</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// About.vue
<template>
  <div>
      <h2>About</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Mine.vue
<template>
  <div>
      <h2>Mine -- {{ name }}</h2>
      <h2>Mine -- {{ age }}</h2>
      <h2>Mine -- {{ address }}</h2>
  </div>
</template>

<script>
export default {
  // 需要获取动态路由参数
  // 使用路由,需要知道4个知识点
  //     1)<router-view />  路由出口
  //     2)<router-link />  a标签   点击跳转
  //     3)$router  对象  有一堆的方法  挂载到当前组件实例上  this
  //     3)$route   对象  有一堆的属性  挂载到当前组件实例上  this

  data(){
    return{
      name:"",
      age:"",
      address:"",
    }
  },
  // 生命周期函数(钩子函数)
  created(){
    // 获取动态路由参数  
    console.log(this.$route);
    console.log(this.$route.params.name);

    this.name = this.$route.params.name
    this.age = this.$route.params.age
    this.address = this.$route.params.address
  }

}
</script>

<style>

</style>
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
// NotFount.vue
<template>
  <div>
      <h2>404</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.vue
<template>
  <div id="app">
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return{
    }
  },
  methods:{
  
  },
  components: {
  },
};
</script>

<style lang="less">
.active{
  color: red;
}
</style>

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

在router-link中进行如下跳转:

<router-link to="/main/wc/18/bj">我的</router-link>
1

# 8, 编程式路由(代码的页面跳转)

# 8.1, 代码的页面跳转

有时候我们希望通过代码来完成页面的跳转,比如点击的是一个按钮

  • 此时,我们可以使用编程式路由
  • this.$router.push("/about")
  • 当然,我们也可以传入一个对象
    • this.$router.push({path:"/about"})
    • this.$router.push({name:"about"})

query方式的参数

  • this.$router.push({path:"/about",query:{name:"wc",age:18}})
  • 在界面中通过 $route.query 来获取参数
    • query: -

params方式的参数

  • this.$router.push({path:"/about",params:{ address:"bj" }})
  • 在界面中通过 $route.params 来获取参数

页面的前进后退

  • router的go方法:
    • router.go(1) 向前移动一条记录,与router.forword()相同
    • router.go(-1) 向后移动一条记录,与router.back()相同
    • router.go(3) 前进3条记录
    • router.go(100) 如果没有那么多记录,静默失败
    • router.go(-100) 如果没有那么多记录,静默失败
  • router也有back:
    • 通过调用 history.back() 回溯历史。相当于 router.go(-1)
  • router也有forward:
    • 通过调用 history.forward() 在历史中前进。相当于 router.go(1)
import VueRouter from "vue-router";
import Vue from "vue";

import Home from "../components/Home"
import About from "../components/About"
import Mine from "../components/Mine"
import NotFount from "../components/NotFount"

Vue.use(VueRouter);

let routes = [
    { path:"/", redirect:"/home" },
    { path:"/home", name:"home", component:Home },
    { path:"/about", name:"about", component:About },
    { path:"/mine", name:"mine", component:Mine },
    { path:"*", component:NotFount },
];

let router = new VueRouter({
    // hash带#    
    // history不带#
    mode:"history",
    routes
})

export default router;
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
// Home.vue
<template>
  <div>
    <h2>Home</h2>
    <button @click="toAbout">去about</button>
    <button @click="forward">forward</button>
  </div>
</template>

<script>
export default {
  methods: {
    toAbout() {
      // 实现跳转到about
      // this上有route  还有router
      // route上有一堆的属性
      // router上有一堆方法
      // 跳转方式一:
      // this.$router.push("/about")

      // 跳转方式二:
      // this.$router.push({ path:"/about" })

      // 跳转方式三:
      // this.$router.push({ name:"about" })

      // 跳转传参方式一:
      // this.$router.push({ name:"about", params:{ address:"bj" } })

      // 跳转传参方式二:
      this.$router.push({ name:"about", query:{ score:"100分" } })

      // replace
      // this.$router.replace({ name:"about", query:{ score:"100分" } })
    },

    forward(){
      // this.$router.forward()
      this.$router.go(1)  // go(1) 等价于 forward
    }
  },
};
</script>

<style>
</style>
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
// About.vue
<template>
  <div>
      <h2>About</h2>
      <!-- <p>{{ $route.params.address }}</p> -->
      <p>{{ $route.query.score }}</p>
      <button @click="back">back</button>
  </div>
</template>

<script>
export default {
  // 4个东西:两个组件   两个对象route  rotuer
  created(){
    console.log(this.$route);
    // console.log(this.$route.params.address);

    console.log(this.$route.query.score);


  },
  methods:{
    back(){
      // this.$router.back();
      this.$router.go(-1); // go(-1) 等价于 back
    }
  }
}
</script>

<style>

</style>
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
// Mine.vue
<template>
  <div>
      <h2>Mine</h2>
  </div>
</template>

<script>
export default {
  data(){
    return{
    }
  },
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// NotFount.vue
<template>
  <div>
      <h2>404</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.vue
<template>
  <div id="app">
    <router-link to="/home" active-class="active">home</router-link> &nbsp;
    <router-link to="/about" active-class="active">about</router-link> &nbsp;
    <router-link to="/mine" active-class="active">mine</router-link> &nbsp;
    <hr>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return{
    }
  },
  methods:{
  
  },
  components: {
  },
};
</script>

<style lang="less">
.active{
  color: red;
}
</style>
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

# 9, 路由导航守卫

# 9.1, 路由导航守卫

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航

全局的前置守卫beforeEach是在导航触发时会被回调的:

  • to:即将进入的路由Route对象
  • from:即将离开的路由Route对象
  • next: 在Vue2中我们是通过next函数来决定如何进行跳转的,是在Vue3中我们是通过返回值来控制的,不再推荐使用next函数,这是因为开发中很容易调用多次next;
// /router/index.js
import VueRouter from "vue-router";
import Vue from "vue";

import Home from "../components/Home"
import About from "../components/About"
import Mine from "../components/Mine"
import Login from "../components/Login"
import NotFount from "../components/NotFount"

Vue.use(VueRouter);

let routes = [
    { path:"/", redirect:"/home" },
    { path:"/home", name:"home", component:Home },
    { path:"/about", name:"about", component:About },
    { path:"/mine", name:"mine", component:Mine },
    { path:"/login", name:"login", component:Login },
    { path:"*", component:NotFount },
];

let router = new VueRouter({
    // hash带#    
    // history不带#
    mode:"history",
    routes
})

// 配置全局路由守卫
// to表示去哪
// from表示从哪里来
// next表示是否放行  放行到哪里
router.beforeEach((to,from,next)=>{
    // console.log("from:",from);
    // console.log("to:",to);
    if(to.path !== "/login"){
        // 去的地方不是/login
        // 只有登录了,才能去/home /about /mine
        if(window.isLogin){
            // 表示已登录
            next();
        }else{
           return next("/login");
        }
    }
    next();
});

export default router;
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
// Home.vue
<template>
  <div>
    <h2>Home</h2>
  </div>
</template>

<script>
export default {
  methods: {
    toAbout() {
     
    },
  },
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// About.vue
<template>
  <div>
      <h2>About</h2>
  </div>
</template>

<script>
export default {
  methods:{
  }
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Mine.vue
<template>
  <div>
      <h2>Mine</h2>
  </div>
</template>

<script>
export default {
  data(){
    return{
    }
  },
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Login.vue
<template>
  <div>
      <button @click="login">登录</button>
  </div>
</template>

<script>
export default {
    methods:{
        login(){
            // 给GO上放一个isLogin是true
            window.isLogin = true;
        }
    }
}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// NotFount.vue
<template>
  <div>
      <h2>404</h2>
  </div>
</template>

<script>
export default {

}
</script>

<style>

</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// App.vue
<template>
  <div id="app">
    <router-link to="/home" active-class="active">home</router-link> &nbsp;
    <router-link to="/about" active-class="active">about</router-link> &nbsp;
    <router-link to="/mine" active-class="active">mine</router-link> &nbsp;
    <hr>
    <router-view />
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return{
    }
  },
  methods:{
  
  },
  components: {
  },
};
</script>

<style lang="less">
.active{
  color: red;
}
</style>

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

其他导航守卫:

  • Vue还提供了很多的其他守卫函数,目的都是在某一个时刻给予我们回调,让我们可以更好的控制程序的流程或者功能
  • https://next.router.vuejs.org/zh/guide/advanced/navigation-guards.html

完整的导航解析流程:

  • 导航被触发。
  • 在失活的组件里调用 beforeRouteLeave 守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫(2.2+)。
  • 在路由配置里调用 beforeEnter。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter。
  • 调用全局的 beforeResolve 守卫(2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
Last Updated: 12/25/2022, 10:02:14 PM