vue3 路由详解

发布于:2025-06-19 ⋅ 阅读:(15) ⋅ 点赞:(0)

路由介绍

Vue 3 的路由功能是构建单页应用(SPA)的核心部分,它允许根据 URL 的变化动态加载不同的组件。

例如这个就是单页应用 他有导航区和展示区 点击每个导航 展示区展示的内容都不变 但是他只是一个页面
在这里插入图片描述

下面是使用路由模拟一个简单单页应用的效果的步骤

  1. 在项目中创建一个 router 文件夹,并在其中创建 index.js 文件来配置路由
//创建一个路由器  并且将他暴露出去

//1.引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/components/Home.vue'
import About from '@/components/About.vue'
import News from '@/components/News.vue'


//2.创建路由器
const router=createRouter({
    history:createWebHistory(),
    routes:[//一个一个的路由规则
        {
            path:'/home',
            component:Home
        },
        {
            path:'/news',
            component:News
        },
        {
            path:'/about',
            component:About
        }
    ]
})

//暴露出去
export default router

  1. 在 main.js 中引入并使用路由
// 导入 Vue 的 createApp 方法,用于创建 Vue 应用
import { createApp } from "vue";

// 导入本地的 App 组件,这是应用的根组件
import App from "./App.vue";

//引入路由器
import router from "./router";

//创建一个应用
const app=createApp(App);

//使用路由器
app.use(router)

app.mount('#app')

  1. 路由的基本使用使用
    router-linkrouter-view 在 Vue 3 中, 用于定义导航链接,而 router-view 用于显示当前路由对应的组件
<template>
    <div class="app"> 
        <Header/>
        <!-- 导航区 -->
        <div class="navigate">
            <RouterLink :to="{
                path:'/home'
            }" active-class="active">首页</RouterLink>
            <RouterLink :to="{
                path:'/news'
            }" active-class="active">新闻</RouterLink>
            <RouterLink :to="{
                path:'about'
            }" active-class="active">关于</RouterLink>
        </div>
        <!-- 内容区 -->
        <div class="main-content">
            <router-view></router-view>
        </div>
    </div>
</template>

<script lang="ts" setup name="App">
    import { RouterView ,RouterLink} from 'vue-router';
    import Header from '@/components/Header.vue'
</script>

<style>
/* 基础样式 */
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    background-color: #f5f5f5;
}

.app {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    box-shadow:0  0 10px rgba(0, 0, 0, 0.1);
}



/* 导航区样式 */
.navigate {
    display: flex;
    justify-content: center;
    margin-bottom: 30px;
}

.navigate a {
    display: inline-block;
    padding: 10px 20px;
    margin: 0 10px;
    text-decoration: none;
    color: #333;
    font-weight: bold;
    border: 2px solid #333;
    border-radius: 5px;
    transition: background-color 0.3s, color 0.3s;
}

.navigate a:hover {
    background-color: #333;
    color: #fff;
}

/* 内容区样式 */
.main-content {
    background-color: #f9f9f9;
    padding: 20px;
    border-radius: 5px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.navigate a.active {
    background-color: #333; /* 激活时的背景颜色 */
    color: #fff; /* 激活时的文字颜色 */
    border-color: #333; /* 激活时的边框颜色 */
}
</style>

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

写路由组件

  • 路由组件About.vue
<template>
    <div class="about">
        <h2>你也喜欢看海贼王?</h2>
    </div>
</template>

<script setup lang="ts" name="About">

</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>
  • 路由组件Home.vue
<template>
    <div class="home">
        <h2>海贼王真好看</h2>
    </div>
</template>

<script setup lang="ts" name="Home">

</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>
  • 路由组件News.vue
<template>
    <div class="news">
        <ul>
            <li><a href="#">新闻001</a></li>
            <li><a href="#">新闻002</a></li>
            <li><a href="#">新闻003</a></li>
            <li><a href="#">新闻004</a></li>
        </ul>
    </div>
</template>

<script setup lang="ts" name="News">
</script>

<style scoped>
/* 新闻列表容器样式 */
.news {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

/* 列表样式 */
.news ul {
    list-style: none; /* 去掉默认的列表样式 */
    padding: 0;
    margin: 0;
}

/* 列表项样式 */
.news li {
    margin-bottom: 10px; /* 添加间距 */
}

/* 链接样式 */
.news a {
    display: block; /* 使链接占据整个列表项 */
    padding: 10px;
    text-decoration: none; /* 去掉下划线 */
    color: #333; /* 文字颜色 */
    border: 2px solid transparent; /* 默认无边框 */
    border-radius: 5px; /* 圆角 */
    transition: background-color 0.3s, border-color 0.3s; /* 平滑过渡效果 */
}

/* 链接悬停样式 */
.news a:hover {
    background-color: #f0f0f0; /* 悬停时的背景颜色 */
    border-color: #ccc; /* 悬停时的边框颜色 */
}

/* 链接激活样式(可选) */
.news a.active {
    background-color: #333; /* 激活时的背景颜色 */
    color: #fff; /* 激活时的文字颜色 */
    border-color: #333; /* 激活时的边框颜色 */
}
</style>

写一般组件

  • Header.vue
<template>
    <div class="about">
        <h1>路由测试</h1>
    </div>
</template>

<script setup lang="ts" name="Header">

</script>

<style scoped>
h1 {
    text-align: center;
    color: #333;
    margin-bottom: 20px;
}
</style>

效果样式

  • 点击首页的效果样式
    在这里插入图片描述

  • 点击新闻的效果样式
    在这里插入图片描述

  • 点击关于的效果样式
    在这里插入图片描述

嵌套路由

配置子路由规则,使用children配置项

//创建一个路由器  并且将他暴露出去

//1.引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
import News from '@/pages/News.vue'
import Detail from '@/pages/Detail.vue'

//2.创建路由器
const router=createRouter({
    history:createWebHistory(),
    routes:[//一个一个的路由规则
        {
            path:'/home',
            component:Home
        },
        {
            path:'/news',
            component:News,
            children:[{
                name:'xiang',
				path:'detail',
				component:Detail
            }]
        },
        {
            path:'/about',
            component:About
        }
    ]
})

//暴露出去
export default router

query参数

路由组件Detail.vue

<template>
    <ul class="news-list">
        <li>编号:{{ query.id }}</li>
        <li>姓名:{{ query.name }}</li>
        <li>能力:{{ query.ability }}</li>
    </ul>
</template>

<script setup lang="ts" name="Detail">
    import { useRoute } from 'vue-router';
    import { toRefs } from 'vue';
    let route=useRoute()

    let {query} =toRefs(route)
</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>

携带query参数的子路由

<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <RouterLink 
                :to="{
                    path:'/news/detail',
                    query:{
                        id:news.id,
                        name:news.name,
                        ability:news.ability
                    }
                }">{{news.name}}</RouterLink>
                
            </li>
        </ul>
        <div class="news-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script setup lang="ts" name="News">
    import { reactive } from 'vue';
    import { RouterView ,RouterLink} from 'vue-router';

    let newsList=reactive([
        {id:'dadada1',name:'路飞',ability:'橡胶果实'},
        {id:'dadada2',name:'白胡子',ability:'地震果实'},
        {id:'dadada3',name:'黑胡子',ability:'暗暗果实'},
        {id:'dadada4',name:'艾斯',ability:'炎炎果实'}
    ])
</script>

<style scoped>
/* 新闻列表容器样式 */
.news {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

/* 列表样式 */
.news ul {
    list-style: none; /* 去掉默认的列表样式 */
    padding: 0;
    margin: 0;
}

/* 列表项样式 */
.news li {
    margin-bottom: 10px; /* 添加间距 */
}

/* 链接样式 */
.news a {
    display: block; /* 使链接占据整个列表项 */
    padding: 10px;
    text-decoration: none; /* 去掉下划线 */
    color: #333; /* 文字颜色 */
    border: 2px solid transparent; /* 默认无边框 */
    border-radius: 5px; /* 圆角 */
    transition: background-color 0.3s, border-color 0.3s; /* 平滑过渡效果 */
}

/* 链接悬停样式 */
.news a:hover {
    background-color: #f0f0f0; /* 悬停时的背景颜色 */
    border-color: #ccc; /* 悬停时的边框颜色 */
}

/* 链接激活样式(可选) */
.news a.active {
    background-color: #333; /* 激活时的背景颜色 */
    color: #fff; /* 激活时的文字颜色 */
    border-color: #333; /* 激活时的边框颜色 */
}
</style>

点击路飞 展示路飞的详情
在这里插入图片描述
点击艾斯 展示艾斯的详情
在这里插入图片描述

params参数

注意
传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path
传递params参数时,需要提前在规则中占位

路由规则

//创建一个路由器  并且将他暴露出去

//1.引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
import News from '@/pages/News.vue'
import Detail from '@/pages/Detail.vue'

//2.创建路由器
const router=createRouter({
    history:createWebHistory(),
    routes:[//一个一个的路由规则
        {
            path:'/home',
            component:Home
        },
        {
            path:'/news',
            component:News, 
            children:[{
                name:'xiang',
				path:'detail/:id/:name/:ability',
				component:Detail
            }]
        },
        {
            path:'/about',
            component:About
        }
    ]
})

//暴露出去
export default router

<template>
    <ul class="news-list">
        <li>编号:{{ params.id }}</li>
        <li>姓名:{{ params.name }}</li>
        <li>能力:{{ params.ability }}</li>
    </ul>
</template>

<script setup lang="ts" name="Detail">
    import { useRoute } from 'vue-router';
    import { toRefs } from 'vue';
    let route=useRoute()

    let {params} =toRefs(route)
</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>
<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <RouterLink 
                :to="{
                    name:'xiang',
                    params:{
                        id:news.id,
                        name:news.name,
                        ability:news.ability
                    }
                }">{{news.name}}</RouterLink>
                
            </li>
        </ul>
        <div class="news-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script setup lang="ts" name="News">
    import { reactive } from 'vue';
    import { RouterView ,RouterLink} from 'vue-router';

    let newsList=reactive([
        {id:'dadada1',name:'路飞',ability:'橡胶果实'},
        {id:'dadada2',name:'白胡子',ability:'地震果实'},
        {id:'dadada3',name:'黑胡子',ability:'暗暗果实'},
        {id:'dadada4',name:'艾斯',ability:'炎炎果实'}
    ])
</script>

<style scoped>
/* 新闻列表容器样式 */
.news {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

/* 列表样式 */
.news ul {
    list-style: none; /* 去掉默认的列表样式 */
    padding: 0;
    margin: 0;
}

/* 列表项样式 */
.news li {
    margin-bottom: 10px; /* 添加间距 */
}

/* 链接样式 */
.news a {
    display: block; /* 使链接占据整个列表项 */
    padding: 10px;
    text-decoration: none; /* 去掉下划线 */
    color: #333; /* 文字颜色 */
    border: 2px solid transparent; /* 默认无边框 */
    border-radius: 5px; /* 圆角 */
    transition: background-color 0.3s, border-color 0.3s; /* 平滑过渡效果 */
}

/* 链接悬停样式 */
.news a:hover {
    background-color: #f0f0f0; /* 悬停时的背景颜色 */
    border-color: #ccc; /* 悬停时的边框颜色 */
}

/* 链接激活样式(可选) */
.news a.active {
    background-color: #333; /* 激活时的背景颜色 */
    color: #fff; /* 激活时的文字颜色 */
    border-color: #333; /* 激活时的边框颜色 */
}
</style>

点击路飞 展示路飞的详情
在这里插入图片描述
点击艾斯 展示艾斯的详情
在这里插入图片描述

props

当接收的是params参数时
<template>
    <ul class="news-list">
        <li>编号:{{ id }}</li>
        <li>姓名:{{ name }}</li>
        <li>能力:{{ ability }}</li>
    </ul>
</template>

<script setup lang="ts" name="Detail">
    defineProps(['id','name','ability'])
</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>
//创建一个路由器  并且将他暴露出去

//1.引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
import News from '@/pages/News.vue'
import Detail from '@/pages/Detail.vue'

//2.创建路由器
const router=createRouter({
    history:createWebHistory(),
    routes:[//一个一个的路由规则
        {
            path:'/home',
            component:Home
        },
        {
            path:'/news',
            component:News, 
            children:[{
                name:'xiang',
				path:'detail/:id/:name/:ability',
				component:Detail,
                props:true
            }]
        },
        {
            path:'/about',
            component:About
        }
    ]
})

//暴露出去
export default router

点击路飞 展示路飞的详情
在这里插入图片描述
点击艾斯 展示艾斯的详情
在这里插入图片描述

当传递的是query参数
//创建一个路由器  并且将他暴露出去

//1.引入createRouter
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import About from '@/pages/About.vue'
import News from '@/pages/News.vue'
import Detail from '@/pages/Detail.vue'

//2.创建路由器
const router=createRouter({
    history:createWebHistory(),
    routes:[//一个一个的路由规则
        {
            path:'/home',
            component:Home
        },
        {
            path:'/news',
            component:News, 
            children:[{
                name:'xiang',
				path:'detail/:id/:name/:ability',
				component:Detail,
                props(route){
                    return route.query
                }
            }]
        },
        {
            path:'/about',
            component:About
        }
    ]
})

//暴露出去
export default router

点击路飞 展示路飞的详情
在这里插入图片描述

编程式路由导航

一个简单的编程式路由导航 当进入三秒后 自己切换到News.vue

<template>
    <div class="home">
        <h2>海贼王真好看</h2>
    </div>
</template>

<script setup lang="ts" name="Home">
    import { onMounted } from 'vue';
    import { useRouter } from 'vue-router';

    const router=useRouter()

    onMounted(()=>{
        setTimeout(() => {
            router.push('news')
        }, 3000);
    })
</script>

<style scoped>
    h2{
       margin-left: 45%;
    }
</style>

如果我想点击查看详情的时候 出现详情信息

<template>
    <div class="news">
        <!-- 导航区 -->
        <ul>
            <li v-for="news in newsList" :key="news.id">
                <button @click="show(news)">查看详情</button>
                <RouterLink 
                :to="{
                    name:'xiang',
                    params:{
                        id:news.id,
                        name:news.name,
                        ability:news.ability
                    }
                }">{{news.name}}</RouterLink>
                
            </li>
        </ul>
        <div class="news-content">
            <RouterView></RouterView>
        </div>
    </div>
</template>

<script setup lang="ts" name="News">
    import router from '@/router';
    import { reactive } from 'vue';
    import { RouterView ,RouterLink,useRouter} from 'vue-router';

    const router1=useRouter()

    let newsList=reactive([
        {id:'dadada1',name:'路飞',ability:'橡胶果实'},
        {id:'dadada2',name:'白胡子',ability:'地震果实'},
        {id:'dadada3',name:'黑胡子',ability:'暗暗果实'},
        {id:'dadada4',name:'艾斯',ability:'炎炎果实'}
    ])

    function show(news:any){
        router1.push({
            name:'xiang',
            query:{
                id:news.id,
                name:news.name,
                ability:news.ability
            }
        })
    }
</script>

<style scoped>
/* 新闻列表容器样式 */
.news {
    max-width: 600px;
    margin: 0 auto;
    padding: 20px;
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

/* 列表样式 */
.news ul {
    list-style: none; /* 去掉默认的列表样式 */
    padding: 0;
    margin: 0;
}

/* 列表项样式 */
.news li {
    margin-bottom: 10px; /* 添加间距 */
}

/* 链接样式 */
.news a {
    display: block; /* 使链接占据整个列表项 */
    padding: 10px;
    text-decoration: none; /* 去掉下划线 */
    color: #333; /* 文字颜色 */
    border: 2px solid transparent; /* 默认无边框 */
    border-radius: 5px; /* 圆角 */
    transition: background-color 0.3s, border-color 0.3s; /* 平滑过渡效果 */
}

/* 链接悬停样式 */
.news a:hover {
    background-color: #f0f0f0; /* 悬停时的背景颜色 */
    border-color: #ccc; /* 悬停时的边框颜色 */
}

/* 链接激活样式(可选) */
.news a.active {
    background-color: #333; /* 激活时的背景颜色 */
    color: #fff; /* 激活时的文字颜色 */
    border-color: #333; /* 激活时的边框颜色 */
}
</style>

在这里插入图片描述

重定向

{
    path:'/',
    redirect:'/about'
}

网站公告

今日签到

点亮在社区的每一天
去签到