阅读视图

发现新文章,点击刷新页面。

vue路由入门2.0

引言

之前已经介绍过了路由的基本使用,vue路由基础入门 ,今天通过一个小案例再来熟练一下路由的使用,并且更加全面的了解路由的各种配置选项。

小栗子

screenshots.gif 目录结构:

image.png

基本的切换效果

  • App.vue代码如下
<template>
  <div class="app">
    <h2 class="title">Vue路由测试</h2>
    <header>
      <!-- 导航区 -->
      <nav class="navigate">
        <RouterLink to="/home" active-class="active">首页</RouterLink>
        <RouterLink :to="{name:'news'}" active-class="active">新闻</RouterLink>
        <RouterLink :to="{path:'/about'}" active-class="active">关于</RouterLink>
      </nav>
    </header>
    <!-- 展示区 -->
    <main class="main-content">
      <RouterView></RouterView>
    </main>
  </div>
</template>

<script setup>

</script>
  • main.js代码如下:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router).mount('#app')

  • 路由配置文件代码如下:
import { createRouter, createWebHistory } from 'vue-router'

const routes = [
    {
        path: '/home',
        name: 'home',
        component: () => import('../views/Home.vue')
    },
    {
        path: '/about',
        name: 'about',
        component: () => import('../views/About.vue')
    },
    {
        path: '/news',
        name: 'news',
        component: () => import('../views/News.vue')
    },
]

const router = createRouter({
    history: createWebHistory(),
    routes
})

export default router
  • 路由组件通常存放在pagesviews文件夹,一般组件通常存放在components文件夹。
  • 通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载

路由的工作模式

  1. history模式

    优点:URL更加美观,不带有#,更接近传统的网站URL

    缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误。

     const router = createRouter({
         history:createWebHistory(), //history模式
     })
    
  2. hash模式

    优点:兼容性更好,因为不需要服务器端处理路径。

    缺点:URL带有#不太美观,且在SEO优化方面相对较差。

     const router = createRouter({
         history:createWebHashHistory(), //hash模式
     })
    

嵌套路由和路由传参

要在新闻页面展示新闻详情

  1. 编写News的子路由:Details.vue
  2. 配置路由规则,添加children配置项:
children: [
            {
                 path: 'detail',
                 name: 'detail',
                 component: () => import('../views/Details.vue'),
            }
        ]

3. 记得去News组件中预留一个<RouterView/> 4. 路由传参

1.query参数

传递参数

<template>
    <div class="news">
        <ul>
            <li v-for="item in newsList" :key="item.id">
                <!-- query传参 -->
                <!-- to的对象写法-->
                <RouterLink :to="{name:'detail', query:{
                    id:item.id,
                    title:item.title,
                    content:item.content
                }}">{{item.title}}</RouterLink>
            </li>
        </ul>
        <div class="content">
            <RouterView/>
        </div>  
    </div>
</template>
  • to的字符串写法:
<router-link :to="`/news/detail?id=${item.id}&title=${item.title}&content=${ item.content}`">{{item.title}}</router-link>

接收参数

  • 在子路由中通过useRoute()方法拿到当前路由实例
<template>
    <div>
        <ul>
            <li>编号:{{ route.query.id }}</li>
            <li>编号:{{ route.query.title }}</li>
            <li>编号:{{ route.query.content }}</li>
        </ul>
    </div>
</template>
<script setup>
import {useRoute} from 'vue-router'
let route = useRoute()
console.log(route.query)
</script>

image.png

  • 使用 query 传参时,参数不会成为路径的一部分,而是作为查询字符串附加在 URL 的末尾。
  • URL 形式

image.png

  • 访问参数:可以通过 route.query.title 和 route.query.content 在组件内部访问这些参数
2.params参数
  • 传递params参数时,需要提前在规则中占位。
path:'detail/:id/:title/:content',

传递参数

<RouterLink :to="{name:'detail', params:{
     id:item.id,
     title:item.title,
     content:item.content
}">{{item.title}}</RouterLink>
  • to的字符串写法:
<RouterLink :to="`/news/detail/${item.id}/${item.title}/${item.content}`">{{item.title}}</RouterLink>

接收参数

  • 在子路由中通过useRoute()方法拿到当前路由实例
<template>
    <div>
        <ul>
            <li>编号:{{ route.params.id }}</li>
            <li>编号:{{ route.params.title }}</li>
            <li>编号:{{ route.params.content }}</li>
        </ul>
    </div>
</template>

<script setup>
import {useRoute } from 'vue-router'
let route = useRoute()
console.log("params:",route.params)
</script>

image.png

  • 使用 params 传参时,参数会成为路径的一部分,并且是通过定义的动态段(dynamic segments)来表示的
  • URL 形式

image.png

  • 访问参数:可以通过 route.params.id 在组件内部访问这个参数。
  • 传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path

props配置

作用:让路由组件更方便的收到参数(可以将路由参数作为props传给组件),不需要在组件内部手动从 route 对象中提取这些值

  • 三种写法
{
name:'detail',
path:'detail/:id/:title/:content',
component:Detail,

  // props的对象写法,作用:把对象中的每一组key-value作为props传给Detail组件
  // props:{id:1,title:新闻1,conten:新闻内容1}, 

  // props的布尔值写法,作用:把收到了每一组params参数,作为props传给Detail组件
     props:true
  
  // props的函数写法,作用:把返回的对象中每一组key-value作为props传给Detail组件
  props(route){
    return route.query
  }
}
  • Details路由组件更方便的收到参数
<template>
    <div>
        <ul>
            <li>编号:{{ id }}</li>
            <li>编号:{{ title }}</li>
            <li>编号:{{ content }}</li>
        </ul>
    </div>
</template>
<script setup>
defineProps(['id','title','content'])
</script>
  • props 和 params 的区别:当使用 props: true 时,只有路径参数 (params) 会被传递给组件。如果你想传递查询参数 (query) 或者其他的 $route 属性,你需要使用对象或者函数的方式来定义 props
  • 确保 props 名称匹配:确保你在路由配置中指定的 props 名称与组件内声明的 props 相匹配,否则组件将无法正确接收这些属性。

编程式导航

编程式路由导航指的是在 Vue 应用中通过 JavaScript 代码来实现页面之间的跳转,而不是依赖于用户点击 <RouterLink> 组件

<template>
    <div class="news">
        <ul>
            <li v-for="item in newsList" :key="item.id">
                   <button @click="showNewsDetail(item)">新闻详情</button>
            </li>
        </ul>
        <div class="content">
            <RouterView/>
        </div>
      
    </div>
</template>

<script setup>
import{reactive} from 'vue'
import {useRouter} from 'vue-router'
const newsList = reactive([
    {
        id:1,
        title:'新闻1',
        content:'新闻内容1'
    },
    {
        id:2,
        title:'新闻2',
        content:'新闻内容2'
    },
    {
        id:3,
        title:'新闻3',
        content:'新闻内容3'
    }
])

const router = useRouter()
const showNewsDetail = (item) => {
    router.push({
        name:'detail', 
        params:{
            id:item.id, 
            title:item.title, 
            content:item.content}
    })
}
</script>
  • to能怎么写,push就能怎么写(字符串路径,路径描述对象,命名路由)。

重定向

  1. 作用:将特定的路径,重新定向到已有路由。

  2. 具体编码:

     {
         path:'/',
         redirect:'/home'
     }
    
  • 项目启动后自动跳转到首页

路由元信息和全局前置守卫

路由元信息(Route Meta Fields)是 Vue Router 提供的一种机制,允许你在定义路由时附加额外的信息到每个路由对象上。这些元信息可以包含任何你想要的数据,比如权限控制所需的标识、页面标题、是否需要认证等。它们不会影响路由的行为,但可以在导航守卫或组件内部访问,以实现更复杂的应用逻辑。

定义路由元信息

在定义路由时,你可以通过 meta 字段为每个路由添加任意数量的自定义属性。

const routes = [
    {
        path: '/home',
        name: 'home',
        meta: {
            title: '首页'  //标题
        },
        component: () => import('../views/Home.vue')
    },
    {
        path: '/about',
        name: 'about',
        meta: {
            title: '关于', //标题
            requiredAuth: true  //权限
        },
        component: () => import('../views/About.vue')
    },
    {
        path: '/news',
        name: 'news',
        meta: { 
            title: '新闻'  // 标题
        },
        component: () => import('../views/News.vue'),
        children: [
            {
                 path: 'detail',
                 name: 'detail',
                 meta: {
                     title: '新闻详情' //标题
                 }
                 component: () => import('../views/Details.vue'),
            }
        ]
    },
    {
        path: '/',
        redirect:'/home'
    }
]
在全局前置守卫中使用

全局前置守卫(Global Before Guards)是 Vue Router 提供的一种导航守卫,用于在每次路由导航开始前执行某些逻辑。它允许你在用户从一个路由跳转到另一个路由之前对这次跳转进行拦截和处理。全局前置守卫对于实现权限控制、加载指示器、页面标题设置等全局性的操作非常有用。 可以通过 router.beforeEach 方法来注册一个全局前置守卫。这个方法接受一个回调函数作为参数,该回调函数会在每次路由变化时被调用。回调函数接收三个参数:

  • to: 即将要进入的目标路由对象。

  • from: 当前导航正要离开的路由对象。

  • next: 一个函数,必须调用它来解析当前的守卫。next() 可以带有一个参数:

    • 不带参数:继续下一个钩子或完成导航。
    • 带有路径字符串或位置描述对象:重定向到新的路径。
    • false: 中断当前的导航。
router.beforeEach((to, from, next) => {
    document.title = to.meta.title || 'Vue Router'  //设置标题
    if (to.meta.requiredAuth) {
         next('/') // 权限控制
    }else next()
})

next 回调:确保每个全局前置守卫中的 next 回调只被调用一次,否则会导致警告甚至在生产环境中使导航失败

❌