Vue_2 --- 路由

0. 概述

路由(route)就是一组key-value的对应关系,多个路由需要经过路由器(router)的管理,为了实现SPA(single page web application)应用,即单页面应用

被导入的组件叫做一般组件,放在components中,由router控制的组件叫做路由组件,放在pages目录中

使用路由切换组件时,销毁老的组件,会走销毁的生命周期,挂载新的组件

1. 环境搭建

1. 下载

# vue2使用vue-router3
npm install vue-router@3

2. 目录创建

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";

// 创建并暴露一个router
export default new VueRouter({
    routes: [
        {
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home
        },
    ]
})

3. 导入并使用

main.js

import Vue from 'vue'
import App from './App.vue'
// 1. 导入VueRouter插件
import VueRouter from "vue-router";
// 2. 导入router对象
import router from "@/router";

Vue.config.productionTip = false
// 3.使用VueRouter插件
Vue.use(VueRouter)

new Vue({
    render: h => h(App),
    router  // 4. 配置router对象
}).$mount('#app')

2. 一级路由

App.vue

<template>
  <div id="app" class="warpper">
    <div class="menu">
      <!-- 1. 要想实现路由跳转,需要使用router-link标签 -->
      <router-link to="/about">我的</router-link>
      <router-link to="/home">关于</router-link>
      <!-- 2. 指定组件呈现的位置 -->
      <router-view></router-view>
    </div>
  </div>
</template>

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

<style>
.warpper{
  display: flex;

}
.menu{
  block-ellipsis: auto;
}
</style>

src/pages/Home.vue

<template>
    <h2>我是Home组件</h2>
</template>
<script>
export default {
  name: "Home",
}
</script>

src/pages/About.vue

<template>
    <h2>我是About组件</h2>
</template>
<script>
export default {
  name: "Home",
}
</script>

3. 嵌套路由(多级路由)

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import message from "@/pages/message.vue";

export default new VueRouter({
    routes: [
        {
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home,
            children:[   // 子路由列表
                {
                    path: "news",   // 子路由不需要加/
                    component: News
                },
                {
                    path: "message",
                    component: message
                },
            ]
        },

    ]
})

src/App.vue

<template>
    <div id="app">
        <div class="row">
            <div class="col-xs-2 col-xs-offset-2">
                <div class="list-group">
                    <router-link class="list-group-item" to="/about">About</router-link>
                    <router-link class="list-group-item" to="/home">Home</router-link>
                </div>
            </div>
            <div class="col-xs-6">
                <div class="panel">
                    <div class="panel-body">
                        <div>
                            <router-view></router-view>
                        </div>
                    </div>
                </div>

            </div>

        </div>
    </div>
</template>

<script>
    export default {
        name: 'App',
        components: {}
    }
</script>

<style>
</style>

src/pages/Home.vue

<template>
    <div>
        <h2>这里是Home的内容</h2>
        <ul class="nav nav-tabs">
            <li>
                <!--子路由需要加上父路由前缀,即/home/news-->
                <router-link class="list-group-item" to="/home/news">News</router-link>
                <router-link class="list-group-item" to="/home/message">message</router-link>
            </li>
            <router-view></router-view>
        </ul>
    </div>
</template>

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

<style scoped>

</style>

src/pages/News.vue

<template>
    <div>
        <h2>这里是News的内容</h2>
        <ul>
            <li>news001</li>
            <li>news002</li>
            <li>news003</li>
        </ul>
    </div>

</template>

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

<style scoped>

</style>

4. 命名路由

简化路由跳转的路径字符串

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

export default new VueRouter({
    routes: [
        {
            name: "about",   // 一级路由的命名
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home,
            children: [
                {
                    path: "news",
                    component: News
                },
                {
                    name: "message",  // 二级路由的命名
                    path: "message",
                    component: Message,
                    children: [
                        {
                            name: "detail",  // 三级路由的命名
                            path: "detail",
                            component: Detail
                        },
                    ]
                },
            ]
        },

    ]
})

1. 一级路由的简写

src/pages/App.vue

<template>
    <div id="app">
        <div class="row">
            <div class="col-xs-2 col-xs-offset-2">
                <div class="list-group">
                    <!-- 一级路由没必要这么写,/about更简单些 -->
<!--                <router-link class="list-group-item" to="/about">About</router-link>-->
                    <router-link class="list-group-item" :to="{name:'about'}">About</router-link>
                    <router-link class="list-group-item" to="/home">Home</router-link>
                </div>
            </div>
            <div class="col-xs-6">
                <div class="panel">
                    <div class="panel-body">
                        <div>
                            <router-view></router-view>
                        </div>
                    </div>
                </div>

            </div>

        </div>
    </div>
</template>

<script>
    export default {
        name: 'App',
        components: {}
    }
</script>

<style>
</style>

2. 二级路由的简写

src/pages/Home.vue

<template>
    <div>
        <h2>这里是Home的内容</h2>
        <ul class="nav nav-tabs">
            <li>
                <!-- 二级路由的简写 -->
<!--            <router-link class="list-group-item" to="/home/news">News</router-link>-->
                <router-link class="list-group-item" :to="{name:'news'">News</router-link>
                <router-link class="list-group-item" to="/home/message">Message</router-link>
            </li>
            <router-view></router-view>
        </ul>
    </div>
</template>

<script>
    export default {
        // eslint-disable-next-line vue/multi-word-component-names
        name: "Home"
    }
</script>

<style scoped>

</style>

3. 三级路由的简写

src/pages/Message.vue

<template>
    <div>
        <ul>
            <li v-for="m in messageList" :key="m.id">
                <router-link :to="{
                    // path:'/home/message/detail',  
                    name:'detail',
                    query:{
                        id:m.id,
                        title:m.title
                    }
                }">
                    {{m.title}}
                </router-link>
            </li>
        </ul>
        <hr>
        <router-view></router-view>
    </div>

</template>

<script>
    export default {
        name: "Messages",
        data() {
            return {
                messageList: [
                    {id: "001", title: "message001"},
                    {id: "002", title: "message002"},
                    {id: "003", title: "message003"},
                ]
            }
        }
    }
</script>

<style scoped>

</style>

5. 路由传参

1. query参数

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

export default new VueRouter({
    routes: [
        {
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home,
            children:[
                {
                    path: "news",
                    component: News
                },
                {
                    path: "message",
                    component: Message,
                    children:[
                        {
                            path: "detail",  // 详情页
                            component: Detail
                        },
                    ]
                },
            ]
        },

    ]
})

src/pages/Message.vue

<template>
    <div>
        <ul>
            <li v-for="m in messageList" :key="m.id">
                <!-- 1. 跳转路由并携带query参数,to=""的模版字符串写法 -->
                <!-- <router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>-->

                <!-- 2. 跳转路由并携带query参数,to=""的对象写法 -->
                <router-link :to="{
                    path:'/home/message/detail',
                    query:{
                        id:m.id,
                        title:m.title
                    }
                }">
                </router-link>
            </li>
        </ul>
        <hr>
        <!-- router-view表示将内容展示在这里 -->
        <router-view></router-view>
    </div>

</template>

<script>
    export default {
        name: "Message",
        data() {
            return {
                messageList: [
                    {id: "001", title: "message001"},
                    {id: "002", title: "message002"},
                    {id: "003", title: "message003"},
                ]
            }
        }
    }
</script>

<style scoped>

</style>

src/pages/Detail.vue

<template>
    <div>
        <ul>
            <!-- this.$route.query 获取传过来的query参数 -->
            <li>消息编号:{{$route.query.id}}</li>
            <li>消息内容:{{$route.query.title}}</li>
        </ul>
    </div>
</template>

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

<style scoped>

</style>

2. params参数

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

export default new VueRouter({
    routes: [
        {
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home,
            children: [
                {
                    path: "news",
                    component: News
                },
                {
                    path: "message",
                    component: Message,
                    children: [
                        {
                            name:"detail",    // 如果使用to=""的对象写法,必须使用命名路由方式,模板字符串都可以
                            path: "detail/:id/:title",   // 1. 声明detail后携带两个param参数,一个是id,一个是title
                            component: Detail
                        },
                    ]
                },
            ]
        },

    ]
})

src/pages/Message.vue

<template>
    <div>
        <ul>
            <li v-for="m in messageList" :key="m.id">
                <!-- 1. 跳转路由并携带query参数,to=""的模版字符串写法 -->
<!--                <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

                <!-- 2. 跳转路由并携带query参数,to=""的对象写法 -->
                <router-link :to="{
                    name:'detail',   // 如果使用的是对象写法,必须使用命名路由,路由必须配置name
                    params:{
                        id:m.id,
                        title:m.title
                    }
                }">
                    {{m.title}}
                </router-link>
            </li>
        </ul>
        <hr>
        <!-- router-view表示将内容展示在这里 -->
        <router-view></router-view>
    </div>

</template>

<script>
    export default {
        name: "Messages",
        data() {
            return {
                messageList: [
                    {id: "001", title: "message001"},
                    {id: "002", title: "message002"},
                    {id: "003", title: "message003"},
                ]
            }
        }
    }
</script>

<style scoped>

</style>

src/pages/Detail.vue

<template>
    <div>
        <ul>
            <!-- this.$route.params 获取传过来的params参数 -->
            <li>消息编号:{{$route.params.id}}</li>
            <li>消息内容:{{$route.params.title}}</li>
        </ul>
    </div>
</template>

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

<style scoped>

</style>

6. 路由 props 配置

用于简化读取params和query参数的代码,谁接收参数在谁的路由中写props配置项

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

export default new VueRouter({
    routes: [
        {
            path: "/about",
            component: About
        },
        {
            path: "/home",
            component: Home,
            children: [
                {
                    path: "news",
                    component: News
                },
                {
                    path: "message",
                    component: Message,
                    children: [
                        {
                            name: "detail",
                            path: "detail/:id/:title",
                            component: Detail,
                            // 第一种写法: 该对象中的所有key-value都会以props的形式,传给Detail组件,但是只能传死数据,一般不用
                            // props:{a:1,b:"hello"}

                            // 第二种写法: 若改配置为true,就会将该路由组件收到的所有params参数,,以props的形式传给Detail组件
                            // query参数不可以
                            // props:true

                            // 第三种写法:常用
                            // query参数和params参数都可以
                            props($route) {
                                // return {
                                //    id: $route.query.id, 
                                //    title: $route.query.title
                                // }
                                return {
                                    id: $route.params.id, 
                                    title: $route.params.title
                                }
                            }
                            // 解构赋值
                            // props({query}) {
                            //     return {id: query.id, title: query.title}
                            // }
                            // props({param}) {
                            //     return {id: param.id, title: param.title}
                            // }
                            // props({param: {id, title}}) {   // 解构赋值后再结构复制
                            //     return {id, title}
                            // }


                        },
                    ]
                },
            ]
        },

    ]
})

src/pages/Detail.vue

<template>
    <div>
        <ul>
            <!-- this.$route.query 获取传过来的query参数 -->
            <li>消息编号:{{id}}</li>
            <li>消息内容:{{title}}</li>
        </ul>
    </div>
</template>

<script>
    export default {
        name: "Deatil",
        props: ["id", "title"]   // 接收props参数
    }
</script>

<style scoped>

</style>

7. 路由记录模式

1. push模式

控制路由跳转时,操作浏览器历史记录的模式,以栈的方式被浏览器存储,router-link 默认是push模式,即追加记录

<!-- 默认是push模式 -->
<router-link class="list-group-item" :to="{name:'news'}">News</router-link>

2. replace模式

控制路由跳转时,操作浏览器历史记录的模式,以栈的方式被浏览器存储,可以开启 router-link 的replace模式,即替换记录

<!-- 以:replace=true 来替换为replace模式,简写为replace -->
<router-link replace class="list-group-item" :to="{name:'news'}">News</router-link>

8. 编程式路由导航(不借助router-link)

1. 指定路由跳转

src/pages/Detail.vue

<template>
    <div>
        <ul>
            <li v-for="m in messageList" :key="m.id">
                <router-link :to="{
                    name:'detail',
                    params:{
                        id:m.id,
                        title:m.title
                    }
                }">
                    {{m.title}}
                </router-link>
                <!-- 给按钮绑定点击事件,并且通过$router来push或replace操作路由跳转记录 -->
                <button @click="pushShow(m)">push查看</button>
                <button @click="replaceShow(m)">replace查看</button>
            </li>
        </ul>
        <hr>
        <router-view></router-view>
    </div>

</template>

<script>
    export default {
        name: "Messages",
        data() {
            return {
                messageList: [
                    {id: "001", title: "message001"},
                    {id: "002", title: "message002"},
                    {id: "003", title: "message003"},
                ]
            }
        },
        methods: {
            pushShow(m) {
                // 指定往detail路径跳转,并将当前路由记录以push的模式压入栈中
                this.$router.push({
                    name: 'detail',
                    params: {
                        id: m.id,
                        title: m.title
                    }
                })
            },
            replaceShow(m) {
                // 指定往detail路径跳转,并将当前路由记录以replace的模式替换栈顶的记录
                this.$router.replace({
                    name: 'detail',
                    params: {
                        id: m.id,
                        title: m.title
                    }
                })
            }
        }
    }
</script>

<style scoped>

</style>

2. 前进/后退

App.vue

<template>
    <div id="app">
        <button @click="back">后退</button>
        <button @click="forward">前进</button>
        <button @click="forwardThree">指定前进3次</button>
        <button @click="backThree">指定后退3次</button>
        <div class="row">
            <div class="col-xs-2 col-xs-offset-2">
                <div class="list-group">

                    <router-link class="list-group-item" to="/about">About</router-link>
                    <router-link class="list-group-item" to="/home">Home</router-link>
                </div>
            </div>
            <div class="col-xs-6">
                <div class="panel">
                    <div class="panel-body">
                        <div>
                            <router-view></router-view>
                        </div>
                    </div>
                </div>

            </div>

        </div>
    </div>
</template>

<script>
    export default {
        name: 'App',
        methods: {
            back() {
                // 后退一步
                this.$router.back()
            },
            forward() {
                // 前进一步
                this.$router.forward()
            },
            forwardThree(){
                // 参数如果是整数代表forward() 3 次
                this.$router.go(3)
            },
            backThree() {
                // 参数如果是负数代表back() 3次
                this.$router.go(-3)
            }
        }
    }
</script>

<style>
</style>

9. 缓存路由组件

用户在News组件中输入了一些内容,切换其他组件再切换回来以后发现News中的内容不见了,是因为切换了组件,销毁了原组件,那么如何缓存之前的组件呢,需要在News组件的父组件中编写代码来控制

src/pages/Home.vue

<template>
    <div>
        <h2>这里是Home的内容</h2>
        <ul class="nav nav-tabs">
            <li>
                <router-link class="list-group-item" to="/home/news">News</router-link>
                <router-link class="list-group-item" to="/home/message">Message</router-link>
            </li>
            <!-- 1. 在router-view展示内容的地方使用 keep-alive 标签包裹起来,使用include来指定缓存哪个路由组件中的name声明的组件名,缓存一个直接写字符串 -->
            <keep-alive include="News">
                <router-view></router-view>
            </keep-alive>
            <!-- 2. 缓存多个,使用数组 -->
            <keep-alive :include="['News','message']">
                <router-view></router-view>
            </keep-alive>
        </ul>
    </div>
</template>

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

<style scoped>

</style>

10. 路由独有的生命周期钩子

当News组件中绑定了定时器,同时News组件被缓存了,当切换到其他路由的时候,此时定时器还在执行中,效率很低

1. activated() -- 激活

<template>
    <div>
        <h2 :style="{opacity}">这里是News的内容</h2>
        <ul>
            <li>news001 <input type="text"></li>
            <li>news002 <input type="text"></li>
            <li>news003 <input type="text"></li>
        </ul>
    </div>

</template>

<script>
    export default {
        name: "News",
        data() {
            return {
                opacity: 1
            }
        },
        // 1. 激活news路由的时候开启定时器开始闪烁
        activated() {
            this.timer = setInterval(() => {
                console.log("@")
                this.opacity -= 0.1
                if (this.opacity <= 0.1) this.opacity = 1
            }, 16)
        },
        deactivated() {
            clearInterval(this.timer)
        }
    }
</script>

<style scoped>

</style>

2. deactivated() -- 失活

<template>
    <div>
        <h2 :style="{opacity}">这里是News的内容</h2>
        <ul>
            <li>news001 <input type="text"></li>
            <li>news002 <input type="text"></li>
            <li>news003 <input type="text"></li>
        </ul>
    </div>

</template>

<script>
    export default {
        name: "News",
        data() {
            return {
                opacity: 1
            }
        },
        activated() {
            this.timer = setInterval(() => {
                console.log("@")
                this.opacity -= 0.1
                if (this.opacity <= 0.1) this.opacity = 1
            }, 16)
        },
        // 1. news路由失活的时候清除定时器
        deactivated() {
            clearInterval(this.timer)
        }
    }
</script>

<style scoped>

</style>

11. 路由守卫

只有符合某些条件才可以进行路由跳转

1. 全局前置路由守卫

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

const router = new VueRouter({
    routes: [
        {
            name: "about",
            path: "/about",
            component: About,
        },
        {
            name: "home",
            path: "/home",
            component: Home,
            children: [
                {
                    name: "news",
                    path: "news",
                    component: News,
                    meta: {   // 路由元信息,即程序员定义的一系列信息,可以用来配置表示这个路由是否开启路由守卫校验,谁需要校验,谁就配置
                        isAuth: true
                    }
                },
                {
                    name: "message",
                    path: "message",
                    component: Message,
                    meta: {   // 路由元信息,即程序员定义的一系列信息,可以用来配置表示这个路由是否开启路由守卫校验,谁需要校验,谁就配置
                        isAuth: true
                    },
                    children: [
                        {
                            name: "detail",
                            path: "detail/:id/:title",
                            component: Detail,
                            props($route) {
                                return {id: $route.params.id, title: $route.params.title}
                            }
                        },
                    ]
                },
            ]
        },

    ]
})

// 全局前置路由守卫,每次路由切换前被调用,初始化时被调用
router.beforeEach((to, from, next) => {
    // to 目标路由, from 从哪个路由来的,next() 放行
    // if (to.path !== "/home") {
    //     if (localStorage.getItem("school") === "一中") next()
    // }
    if (to.meta.isAuth) {
        if (localStorage.getItem("school") === "一中") next()
    }else{
        next()
    }
})

export default router

2. 全局后置路由守卫

通常用于切换页签标题

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

const router = new VueRouter({
    routes: [
        {
            name: "about",
            path: "/about",
            component: About,
            meta: {
                title: "关于"  // 配置页签标题
            }
        },
        {
            name: "home",
            path: "/home",
            component: Home,
            meta: {
                title: "主页"  // 配置页签标题
            },
            children: [
                {
                    name: "news",
                    path: "news",
                    component: News,
                    meta: {
                        isAuth: true,
                        title: "新闻" // 配置页签标题
                    }
                },
                {
                    name: "message",
                    path: "message",
                    component: Message,
                    meta: {
                        isAuth: true,
                        title: "消息" // 配置页签标题
                    },
                    children: [
                        {
                            name: "detail",
                            path: "detail/:id/:title",
                            component: Detail,
                            meta: {
                                isAuth: true,
                                title: "详情" // 配置页签标题
                            },
                            props($route) {
                                return {id: $route.params.id, title: $route.params.title}
                            }
                        },
                    ]
                },
            ]
        },

    ]
})

router.beforeEach((to, from, next) => {
    if (to.meta.isAuth) {
    	if (localStorage.getItem("school") === "一中") next()
    }else{
        document.title = to.meta.title || "监控系统"
    	next()
    }
})

// 后置路由守卫,每次路由切换后被调用,初始化时被调用
router.afterEach((to,) => {
    // to 目标路由, from 从哪个路由来的
    document.title = to.meta.title || "监控系统"  // 设置页签标题
})

export default router

public/index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <!-- CSS -->
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.2/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <title>监控系统</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

3. 独享守卫

src/router/index.js

import VueRouter from "vue-router";
import About from "@/pages/About.vue";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import Message from "@/pages/Message.vue";
import Detail from "@/pages/Detail.vue";

const router = new VueRouter({
    routes: [
        {
            name: "about",
            path: "/about",
            component: About,
            meta: {
                title: "关于"
            }
        },
        {
            name: "home",
            path: "/home",
            component: Home,
            meta: {
                title: "主页"
            },
            children: [
                {
                    name: "news",
                    path: "news",
                    component: News,
                    meta: {
                        isAuth: true,
                        title: "新闻"
                    },
                    beforeEnter: (to, from, next) => {   // News组件的独享路由守卫,只有前置没有后置
                        if (to.meta.isAuth) {
                            if (localStorage.getItem("school") === "一中") next()
                        }else{
                            next()
                        }
                    }
                },
                {
                    name: "message",
                    path: "message",
                    component: Message,
                    meta: {
                        isAuth: true,
                        title: "消息"
                    },
                    children: [
                        {
                            name: "detail",
                            path: "detail/:id/:title",
                            component: Detail,
                            meta: {
                                isAuth: true,
                                title: "详情"
                            },
                            props($route) {
                                return {id: $route.params.id, title: $route.params.title}
                            }
                        },
                    ]
                },
            ]
        },

    ]
})

router.beforeEach((to, from, next) => {
    // if (to.meta.isAuth) {
    //     if (localStorage.getItem("school") === "一中") next()
    // }else{
    //     next()
    // }
    next()
})

router.afterEach((to,) => {
    document.title = to.meta.title || "监控系统"
})

export default router

4. 组件内路由守卫

src/pages/About.vue

<template>
    <div>
        <h2>这里是About的内容</h2>
    </div>
</template>

<script>
    export default {
        name: "About",
        // 1. 通过路由规则进入该组件时调用,必须点击router-link标签
        beforeRouteEnter(to,from,next){
            next()
        },
        // 2. 通过路由规则离开该组件时调用,必须点击router-link标签
        beforeRouteLeave(to,from,next){
            next()
        }
    }
</script>

<style scoped>

</style>

12. 路由器工作模式

1. hash

Vue中/#/后的所有东西,都算作是hash值,/#/包括后面的所有东西都不会发送给服务器

http://localhost:8080/#/a/b/ 服务器接收到的请求为: /,/#/及以后得所有东西都是前端使用的

2. history

没有hash值,但是所有的路径都会发送给服务器

页面点击没问题,当页面刷新时,会出现404的问题,

1. 通过后端的路由规则解决这个问题,这里以Django为例

urls.py

from django.views.generic import TemplateView
from django.urls import path
 
urlpatterns = [
    # ...其他Django路由...
 
    # Vue.js 应用的路由
    path('', TemplateView.as_view(template_name='index.html')),
]

2. 通过nginx解决这个问题

location /{
    error_page  404  /index.html;  # 将404页面转交给index.html处理
}

3. 修改工作模式

import VueRouter from "vue-router";

const router = new VueRouter({
    mode:"history",   // 指定路由系统的工作模式,默认为hash模式
})
export default router

4. 对比

hash模式:

  1. 地址栏中永远带着#号,不美观
  2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
  3. 兼容性较好

histroy模式:

  1. 地址栏干净,美观
  2. histroy模式比hash模式的兼容性略差
  3. 应用部署上线时,需要通过后端人员或nginx配置,解决刷新页面服务端404的问题
posted @ 2024-03-25 17:25  河图s  阅读(33)  评论(0)    收藏  举报