写一个最基本的路由导航
下载、创建、使用路由
下载路由
npm i vue-router
创建路由
先在 src 内去创建一个 router 文件夹
在文件夹内创建一个 index 文件
index.ts 内代码
// 创建一个路由器,并暴露出去
// 引入createRouter
import { createRouter, createWebHistory } from "vue-router"
// 引入可能要呈现的组件
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Mine from '@/components/Mine.vue'
// 创建路由器
const router = createRouter({
history:createWebHistory(),
routes: [
{
path:'/home',
component:Home
},
{
path:'/news',
component:News
},
{
path:'/about',
component:About
},
{
path:'/mine',
component:Mine
},
]
})
// 暴露 router 出去
export default router
使用路由
在 mian.ts 文件内,去引入、注册路由
mian.ts 代码
// 引入createApp用于创建应用
import { createApp } from 'vue'
// 引入App根组件
import App from './App.vue'
// 引入Router路由器
import router from './router'
// 创建一个应用
const app = createApp(App)
// 使用路由器
app.use(router)
// 挂载整个应用到容器中
app.mount('#app')
实现导航切换
示例:
在App.vue文件内,引入 RouterView, RouterLink 实现 路由跳转
App.vue 代码
<template>
<div class="app">
<!-- 导航区 -->
<div class="nav">
<RouterLink to="/home" active-class="active">首页</RouterLink>
<RouterLink to="/mine" active-class="active">我的</RouterLink>
</div>
<!-- 展示区 -->
<div class="main">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup namae="App">
import { RouterView, RouterLink } from 'vue-router'
</script>
使用 RouterLink 标签去包裹要跳转的路径,类似于 a标签
使用 to 去填写要跳转的具体路径 类似于 href=“”
使用 RouterView ,让页面中展示跳转的内容
active-class 是当前所在路由的css样式,类似于 active
注意的点
1. 路由组件通常放在 pages 或 views 文件夹,一般组件通常放在 component 文件夹内
2. 通过点击导航,视觉效果上“消失”了的路由组件,默认是被销毁掉的,需要的时候再去挂载
路由器工作模式
1. history 模式
Vue2: mode:'history'
Vue3: history:createWebHistory()
React: BrowserRouter
优点:URL 更加美观,不带有 #,更接近传统网站 URL
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有 404 错误
const router = createRouter({ history:createWebHistory(), /******/ })
2. hash 模式
优点:兼容性更好,因为不需要服务器端处理路径
缺点:URL 带有 # 不太美观,且在 SEO 优化方面相对较差
const router = createRouter({ history:createWebHashHistory(), /******/ })
to的两种写法
第一种:字符串写法
第二种:对象写法
// 第一种
<RouterLink to="/home" active-class="active">首页</RouterLink>
// 第二种 可以用path 也可以用name
<RouterLink :to="{path:'/home'}" active-class="active">首页</RouterLink>
<RouterLink :to="{name:'/shouye'}" active-class="active">首页</RouterLink>
嵌套路由
就是在第一层路由的基础上加上它的子路由
示例代码:
{
name:'myNews',
path:'/news',
component:News,
children:[
{
path:'detail',
component:newsDetail,
}
]
},
注意:children 内的 path 路径不需要带 '/'
路由传参
query传参
示例代码:
第一种方式
父组件
<template>
<div class="person">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 第一种写法 -->
<RouterLink active-class="active" :to=" `/news/detail?id=${item.id}&title=${item.title}&content=${item.content}`">{{ item.title }}</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="news">
import { reactive } from 'vue'
import { RouterView,RouterLink } from 'vue-router'
let newsList = reactive([
{id: '001', title: '歌手张杰在武汉连开三场演唱会!', content:'近日,歌手张杰将在武汉连开三场演唱会!'},
{id: '002', title: '此为第二个新闻', content:'2222222222'},
{id: '003', title: '此为第三个新闻', content:'3333333333'},
{id: '004', title: '此为第四个新闻', content:'4444444444'},
])
</script>
子组件
<script setup lang="ts">
import { toRefs } from 'vue';
import { useRoute } from 'vue-router'
let route = useRoute()
let { query } = toRefs(route)
</script>
<template>
<ul class="news-list">
<li>编号:{{ query.id }}</li>
<li>标题:{{ query.title }}</li>
<li>内容:{{ query.content }}</li>
</ul>
</template>
第二种方式
父组件
<template>
<div class="person">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 第二种写法 -->
<RouterLink
:to="{
path:'newsDetail',
query: {
id:item.id,
title:item.title,
content:item.content,
}
}">
</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="news">
import { reactive } from 'vue'
import { RouterView,RouterLink } from 'vue-router'
let newsList = reactive([
{id: '001', title: '歌手张杰在武汉连开三场演唱会!', content:'近日,歌手张杰将在武汉连开三场演唱会!'},
{id: '002', title: '此为第二个新闻', content:'2222222222'},
{id: '003', title: '此为第三个新闻', content:'3333333333'},
{id: '004', title: '此为第四个新闻', content:'4444444444'},
])
</script>
子组件
<script setup lang="ts">
import { toRefs } from 'vue';
import { useRoute } from 'vue-router'
let route = useRoute()
let { query } = toRefs(route)
console.log('route', route);
</script>
<template>
<ul class="news-list">
<li>编号:{{ query.id }}</li>
<li>标题:{{ query.title }}</li>
<li>内容:{{ query.content }}</li>
</ul>
</template>
两种方式区别就是 前面讲到的 to的两种写法
第一种:是通过 ·· 和 ? 去拼接字符串的,在路径后接上?去传递值
第二种:是通过 query 传递值
params传参
注意:
使用 params 传参时,需要提前在规则中去占位
如果某个参数是不一定要传的,可以在规则中形参名后面加上 ? 表示非必传
第一种
父组件
<template>
<div class="person">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 第一种写法 -->
<RouterLink active-class="active" :to=" `/news/detail/${item.id}/${item.title}/${item.content}`">{{ item.title }}</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="news">
import { reactive } from 'vue'
import { RouterView,RouterLink } from 'vue-router'
let newsList = reactive([
{id: '001', title: '歌手张杰在武汉连开三场演唱会!', content:'近日,歌手张杰将在武汉连开三场演唱会!'},
{id: '002', title: '此为第二个新闻', content:'2222222222'},
{id: '003', title: '此为第三个新闻', content:'3333333333'},
{id: '004', title: '此为第四个新闻', content:'4444444444'},
])
</script>
子组件
<template>
<ul class="news-list">
<li>编号:{{ params.id }}</li>
<li>标题:{{ params.title }}</li>
<li>内容:{{ params.content }}</li>
</ul>
</template>
<script setup lang="ts">
import { toRefs } from 'vue';
import { useRoute } from 'vue-router'
let route = useRoute()
let { params } = toRefs(route)
console.log('route', route);
</script>
router文件
// 创建路由器
const router = createRouter({
history:createWebHistory(),
routes: [
...
{
name:'myNews',
path:'/news',
component:News,
children:[
{
name: 'newsDetail',
path:'detail/:id/:title/:content',
component:newsDetail,
}
]
},
...
]
})
使用字符串去跳转时,参数与参数之间是用 / 分割的
第二种
父组件
<template>
<div class="person">
<!-- 导航区 -->
<ul>
<li v-for="item in newsList" :key="item.id">
<!-- 第二种写法 -->
<RouterLink
:to="{
name:'newsDetail',
params: {
id:item.id,
title:item.title,
content:item.content,
}
}">
</RouterLink>
</li>
</ul>
<!-- 展示区 -->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="news">
import { reactive } from 'vue'
import { RouterView,RouterLink } from 'vue-router'
let newsList = reactive([
{id: '001', title: '歌手张杰在武汉连开三场演唱会!', content:'近日,歌手张杰将在武汉连开三场演唱会!'},
{id: '002', title: '此为第二个新闻', content:'2222222222'},
{id: '003', title: '此为第三个新闻', content:'3333333333'},
{id: '004', title: '此为第四个新闻', content:'4444444444'},
])
</script>
params 传参时, to选择用对象写法,就要用name配置项,不能用 path ,不然会报错
props配置
作用:让路由组件更方便收到参数(可以将路由参数作为 props 传递给组件)
router文件内代码:
// 创建路由器
const router = createRouter({
history:createWebHistory(),
routes: [
...
{
name:'myNews',
path:'/news',
component:News,
children:[
{
name: 'newsDetail',
path:'detail/:id/:title/:content',
component:newsDetail,
// 第一种写法,将路由收到的所有 params 参数作为props传给路由组件
// props:true
// 第二种写法,函数写法,可以自己决定将什么作为 props 给路由组件
props(route) {
return route.query
}
// 第三种写法,对象写法,可以自己决定将什么作为 props 给路由组件
// props:{
// id: 123,
// title: 'props',
// content: '内容~'
// }
}
]
},
...
]
})
组件内代码
<template>
<ul class="news-list">
<li>编号:{{ id }}</li>
<li>标题:{{ title }}</li>
<li>内容:{{ content }}</li>
</ul>
</template>
<script setup lang="ts">
import { defineProps } from 'vue';
defineProps(['id', 'title', 'content'])
</script>
props配置有三种
第一种是 props:true,这种是只能传 params的值
第二种是函数写法,可以传递 params 也可以传递 query的值
第三种是对象写法,值只能写固定的,很少用
在组件内用 defineProps 属性,去接收值
格式:defineProps(['id', 'title', 'content'])
可以直接在模版内去使用 id title等
replace属性
1. 作用:控制路由跳转时操作浏览器历史记录的模式
2. 浏览器的历史记录有两张写入方式:分别为 push 和 replace
push 是追加历史记录(默认值)
replace 是替换当前记录
3. 开启 replace 模式
<RouterLink replace ............>News</RouterLink >
使用此属性可以覆盖记录,无法回跳
编程式导航
脱离 <RouterLink>实现路由跳转
实现简单的跳转
<script lang="ts" setup name="home">
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
onMounted(()=>{
setTimeout(() => {
router.push('/news')
},2000)
})
</script>
引入 useRouter,然后用常量接收,最后 .push 去跳转
携带参数跳转
<script lang="ts" setup name="news">
import { reactive } from 'vue'
import { RouterView,RouterLink, useRouter } from 'vue-router'
const router = useRouter()
interface NewsInter {
id: string,
title: string,
content: string,
}
function showNewsDetail(item:NewsInter) {
router.push({
name:'newsDetail',
params: {
id:item.id,
title:item.title,
content:item.content,
}
})
}
</script>
路由重定向
实现原理:在路由文件,一级路由后加上重定向代码。如下
{
path:'/',
redirect:'/home'
}
就能实现 进入页面就能重定向到 home 页