路由和路由守卫

路由

  • 1.路由就是一组key-value的对应关系(key为路径,value可能是function或component)
  • 2.多个路由,需要经过路由器管理

SPA(single page web application)应用

  • 单页面Web应用:整个页面只有一个完整的页面
  • 点击页面中的导航链接不会刷新页面,只会做页面的局部更新
  • 数据需要通过ajax请求获取

路由切换实例
App.vue

<template>
    <!-- vue中借助router-link标签实现页面的路由跳转 -->
    <router-link to="/home">home</router-link><br>
    <router-link to="/about">about</router-link>
    
<div>
    vue中指定组件呈现位置
    <router-view></router-view>
</div>
        
</template>
<script setup>
</script>

router文件夹下的index文件

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/home',
      name: 'home',
      component: HomeView
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import('../views/AboutView.vue')
    }
  ]
})

export default router

about页面

<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
</template>

<style>
@media (min-width: 1024px) {
  .about {
    min-height: 100vh;
    display: flex;
    align-items: center;
  }
}
</style>

home页面

<script>
// import TheWelcome from '../components/TheWelcome.vue'
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    // 在其他方法或是生命周期中也可以调用方法
    this.increment()
  }
}

</script>

<template>
  <button @click="increment">{{ count }}</button>

</template>

路由的注意点
1.路由组件通常存放在pages(或views)文件夹中,一般组件通常存放在components文件夹
2.通过切换,“隐藏”了路由组件,默认是被销毁掉的,需要的时候再去挂载
3.每个组件都有自己的$route属性,里面存储着自己的路由信息
4.整个应用只有一个router,可以通过组件的$router属性获取到

嵌套路由(多级路由)
在home组件中增加子路由页面

<script>
</script>
<template>
  <h2>Home组件内容</h2>
  <router-link to="/home/news">news</router-link>&nbsp;
  <router-link to="/home/messages">messages</router-link>
  <router-view></router-view>
</template>

home路由配置中通过children增加子路由的配置

{
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'news',
          name:'news',
          component:News,
        },
        {
          path: 'messages',
          name:'messages',
          component:Messages,
        }
      ]
    },

news

<template>
    <div>
        <ul>
            <li>张震岳</li>
            <li>周华健</li>
            
        </ul>
    </div>
</template>

messages

<template>
    <div>
        <ul>
            <li>刘德华</li>
            <li>张学友</li>
            <li>郭富城</li>
            <li>黎明</li>
        </ul>
    </div>
</template>

路由传参query方式

<template>
    <div>
        <ul>
            <li v-for="m in messagesList" :key="m.id">
                <router-link 
                :to="{path:'/home/messages/detail',
                query:{id:m.id,title:m.title}}">
                {{m.title}}</router-link>
            </li>
        </ul>
    </div>
    <router-view></router-view>
</template>
<script setup>
import {reactive} from 'vue'
let messagesList=reactive([
    {id:'001',title:'title001'},
    {id:'002',title:'title002'},
    {id:'003',title:'title003'}
])
</script>

路由接受参数

<template>
    <div>
        <h2>详情页</h2>
        <ul>
            <li>消息编号{{route.query.id}}</li>
            <li>消息标题{{route.query.title}}</li>
        </ul>
    </div>
</template>
<script setup>
import {useRoute} from 'vue-router'
const route=useRoute()
console.log(route);
</script>

命名路由:可以简化路由跳转
路径过长时通过增加name属性,可以简化路由

{
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'news',
          name:'news',
          component:News,
        },
        {
          path: 'messages',
          name:'messages',
          component: Messages,
          children: [
            {
              path: 'detail',
              name: 'detail',
              component:Detail
              
            }
          ]
        }
      ]
    },
            <li v-for="m in messagesList" :key="m.id">
                <router-link 
                :to="{name:'detail',
                query:{id:m.id,title:m.title}}">
                {{m.title}}</router-link>
            </li>

路由传参params
注意点:当使用params传参时,若使用to的对象写法,则不能使用path配置项,必须使用命名路由也就是name
传参

<template>
    <div>
        <ul>
            <li v-for="m in messagesList" :key="m.id">
                <router-link 
                :to="{name:'detail',
                params:{id:m.id,title:m.title}}">
                {{m.title}}</router-link>
            </li>
        </ul>
    </div>
    <router-view></router-view>
</template>
{
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'news',
          name:'news',
          component:News,
        },
        {
          path: 'messages',
          name:'messages',
          component: Messages,
          children: [
            {
              path: 'detail/:id/:title',
              name: 'detail',
              component:Detail
              
            }
          ]
        }
      ]
    },

接受参数和query方式一样

通过props传参

    {
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'news',
          name:'news',
          component:News,
        },
        {
          path: 'messages',
          name:'messages',
          component: Messages,
          children: [
            {
              path: 'detail/:id/:title',
              name: 'detail',
              component: Detail,
              //props,值为布尔值,若为真,就会把该路由组件收到的所有params参数传给detail组件
              props:true
              
            }
          ]
        }
      ]
    },

接受参数

<template>
    <div>
        <h2>详情页</h2>
        <ul>
            <!-- <li>消息编号{{route.params.id}}</li>
            <li>消息标题{{route.params.title}}</li> -->
            <li>消息编号{{id}}</li>
            <li>消息标题{{title}}</li>
        </ul>
    </div>
</template>
<script setup>
import {useRoute} from 'vue-router'
import {defineProps,toRefs} from 'vue'

const props=defineProps(['id','title'])
const {id,title}=toRefs(props)
</script>

页面不可以返回
通过在route-link中加入replace=“true”,则不可以返回上一个页面,原理是,封闭的栈中,后一条记录会替换上一条记录

<router-link replace="true" to="/home">home</router-link><br>
编程式导航
例如给button绑定页面前进后退,是否消除记录式的前进
push、replace、back、forword、go
具体包含哪些操作可以打印router查看
import {useRouter} from 'vue-router'
const router=useRouter()
console.log(router);
<template>
    <div>
        <ul>
            <li v-for="m in messagesList" :key="m.id">
                <router-link 
                :to="{name:'detail',
                query:{id:m.id,title:m.title}}">
                {{m.title}}</router-link>
                <button @click="pushShow(m)">push查看</button>
                <button @click="replaceShow(m)">replace查看</button>

            </li>
        </ul>
    </div>
    <router-view></router-view>
</template>
<script setup>
import {reactive} from 'vue'
import {useRouter} from 'vue-router'
const router=useRouter()
console.log(router);
let messagesList=reactive([
    {id:'001',title:'title001'},
    {id:'002',title:'title002'},
    {id:'003',title:'title003'}
])
const pushShow=(m)=>{
    router.push({
        name:'detail',
        query:{
            id:m.id,
            title:m.title
        }
    })
}
const replaceShow=(m)=>{
    router.replace({
        name:'detail',
        query:{
            id:m.id,
            title:m.title
        }
    })
}
</script>

缓存路由组件

<script setup>
import {ref} from 'vue'

</script>
<template>
  <h2>Home组件内容</h2>
  <router-link to="/home/news">news</router-link>&nbsp;
  <router-link to="/home/messages">messages</router-link>
 

<router-view v-slot="{ Component }">
  <keep-alive>
    <component :key="$route.name" :is="Component" v-if="$route.meta.keepAlive" />
  </keep-alive>
  <component :key="$route.name" :is="Component" v-if="!$route.meta.keepAlive" />
</router-view>
</template>
{
      path: '/home',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: 'news',
          name:'News',
          component: News,
          meta: {
            keepAlive:true
          }
        },
        {
          path: 'messages',
          name:'messages',
          component: Messages,
          children: [
            {
              path: 'detail',
              name: 'detail',
              component: Detail,
              //props,值为布尔值,若为真,就会把该路由组件收到的所有params参数传给detail组件
              // props:true
              
            }
          ]
        }
      ]
    },
//第二种路由缓存方式
<router-view v-slot="{ Component }" > <KeepAlive :include="News" > <component :is="Component" /> </KeepAlive> </router-view>

 

两个新的生命周期钩子
作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态
activated路由组件被激活时触发
deactivated路由组件失活时触发

路由守卫
全局路由守卫、独享路由守卫、组件内路由守卫

全局路由守卫
全局前置路由:router.beforeEach((to,from,next)=>{})
全局后置路由:router.afterEach((to,from)=>{})

独享路由守卫:
beforeEnter((to,from,next)=>{})

组件内路由守卫:
beforeRouteEnter((to,from,next)=>{})
afterRouteLeave((to,from,next)=>{})

 


posted @ 2022-12-06 09:27  终究还是避免不了遗憾  阅读(94)  评论(0编辑  收藏  举报