Vue3学习02 路由
- 路由
- 基本使用
- 两个注意点
- 路由器工作模式
- to的两种写法
- 【命名路由】
- 【嵌套路由】
- 路由传参
- query参数
- params参数
- 路由规则的props配置
- replace属性
- 编程式导航
- 重定向
路由
路由器检测到路由的变化,路径变化,对应的组件也变化
基本使用
想使用路由:
① 确定导航区、展示区
② 请来路由器 npm i vue-router
③ 指定路由的具体规则(什么路径、对应着什么组件)
在 src 底下 创建一个文件夹 router/index.ts (vue3中是ts不是js)
④ 形成一个一个的 .vue 文件
- 配置路由 src/router/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';// 第二步 创建路由器
const router = createRouter({history:createWebHistory(), // 路由器的工作模式routes: [{path: '/home',component: Home,},{path: '/news',component: News,},{path: '/about',component: About,}]
})export default router
- main.ts
import {createApp} from 'vue'
import App from './App.vue'// 引入路由器
import router from './router'// createApp(App).mount('#app')// 创建应用
const app = createApp(App)
// 使用路由器
app.use(router)
// 挂载
app.mount('#app')
- app.vue :RouterLink、RouterView
<template><div class="app"><h2 class="title">Vue路由测试</h2><!-- 导航区 --><div class="navigate"><RouterLink to="/home" active-class="xiaozhupeiqi">首页</RouterLink><RouterLink to="/news" active-class="xiaozhupeiqi">新闻</RouterLink><RouterLink to="/about" active-class="xiaozhupeiqi">关于</RouterLink></div><!-- 展示区 --><div class="main-content"><RouterView></RouterView></div></div>
</template><script lang="ts" setup name="App"></script>
两个注意点
-
路由组件通常存放在
pages
或views
文件夹,一般组件通常存放在components
文件夹。 -
通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。
通过生命周期函数验证 onMounted 、onUnMounted
路由器工作模式
import {createRouter,createWebHistory,createWebHashHistory} from ‘vue-router’
-
history
模式优点:
URL
更加美观,不带有#
,更接近传统的网站URL
。缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有
404
错误。const router = createRouter({history:createWebHistory(), //history模式/******/ })
-
hash
模式优点:兼容性更好,因为不需要服务器端处理路径。
缺点:
URL
带有#
不太美观,且在SEO
优化方面相对较差。const router = createRouter({history:createWebHashHistory(), //hash模式/******/ })
to的两种写法
<!-- 第一种:to的字符串写法 -->
<router-link active-class="active" to="/home">主页</router-link><!-- 第二种:to的对象写法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
对象写法,to的前面必须加一个冒号,表示绑定,实际路径为 双引号内部的对象。如果不写绑定,就是字符串
【命名路由】
作用:可以简化路由跳转及传参(后面就讲)。
给路由规则命名:
routes:[{name:'zhuye', // 给路由命名path:'/home',component:Home},{name:'xinwen', // 给路由命名path:'/news',component:News,},{name:'guanyu', // 给路由命名path:'/about',component:About}
]
跳转路由:
<!--简化前:需要写完整的路径(to的字符串写法) -->
<router-link to="/about">跳转</router-link><!--简化后:直接通过名字跳转(to的对象写法配合name属性) -->
<router-link :to="{name:'guanyu'}">跳转</router-link>
【嵌套路由】
1、编写News
的子路由:Detail.vue
2、配置路由规则,使用children
配置项:
children配置项里面的路径 path 不加斜杠
const router = createRouter({history:createWebHistory(),routes:[{name:'zhuye',path:'/home',component:Home},{name:'xinwen',path:'/news',component:News,children:[{name:'xiang',path:'detail', //这里不写斜杠component:Detail}]},{name:'guanyu',path:'/about',component:About}]
})
export default router
3、跳转路由(记得要加完整路径):
<router-link to="/news/detail">xxxx</router-link>
<!-- 或 -->
<router-link :to="{path:'/news/detail'}">xxxx</router-link>
4、记得去Home
组件中预留一个<router-view>
<template><div class="news"><nav class="news-list"><RouterLink v-for="news in newsList" :key="news.id" :to="{path:'/news/detail'}">{{news.name}}</RouterLink></nav><div class="news-detail"><RouterView/></div></div>
</template>
路由传参
route 路由:一组对应关系
router 路由器:管理路由
query参数
-
query写法(带问号):/news/detail?id=111&title=haha
-
query参数 有两种写法 是因为 to有两种写法
to的两种写法:
<RouterLink to="/news/detail">{{ news.title }}
</RouterLink><!-- to的对象写法,前面需要加冒号 -->
<RouterLink :to="{path: '/news/detail', //或者 name:'xiangqing'}">{{ news.title }}
</RouterLink>
-
传递参数
① to的字符串写法:配合模板字符串。to前面加一个冒号,表示它实际上的内容是双引号里面的字符串(模板字符串)
② to的对象写法
<!-- 跳转并携带query参数(to的字符串写法) --> <li v-for="news in newsList" :key="news.id"><RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`">{{ news.title }}</RouterLink> </li><!-- 跳转并携带query参数(to的对象写法) --> <RouterLink :to="{//name:'xiangqing', //用name也可以跳转path:'/news/detail',query:{id:news.id,title:news.title,content:news.content}}" >{{news.title}} </RouterLink>
-
接收参数:
这里 useRoute 是 hooks(usexxx 命名规则)
import {useRoute} from 'vue-router' const route = useRoute() // 打印query参数 console.log(route.query)
如果想解构 route.query,会失去响应式。从一个响应式对象身上解构属性,该属性必定丢失响应式。要使用 toRefs.
正确做法:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query参数
let {query} = toRefs(route)
params参数
哈哈 嘿嘿 呼呼 是参数,但是vue会认为是路由规则。所以需要在路由中配置规则,告诉路由哪部分不算路径。
<RouterLink to="/news/detail/哈哈/嘿嘿/呼呼">{{ news.title }}</RouterLink>
1、配置规则
需要在 /router/index.ts中先配置规则
{path: '/news',component: News,children: [{name:'xiangqing',path: 'detail/:id/:title/:content', //占位component: Detail}]}
数据content 可传可不传的写法:
path: 'detail/:id/:title/:content?'
表示content内容可传可不传
2、传递参数:
备注1:传递params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。
备注2:传递params
参数时,需要提前在规则中占位。
<li v-for="news in newsList" :key="news.id"><!-- 字符串写法 --><RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink><!-- 对象写法 --><RouterLink :to="{name:'xiangqing',params:{id: news.id,title: news.title,content: news.content} }">{{ news.title }}</RouterLink></li>
3、接收参数:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印params参数
console.log(route.params)
路由规则的props配置
- /router/index.ts
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件)
{name:'xiang',path:'detail/:id/:title/:content',component:Detail,// props的布尔值写法,作用:把收到了每一组【params参数】,作为props传给Detail组件// props:true// props的对象写法,作用:把对象中的每一组key-value作为props传给Detail组件// props:{a:1,b:2,c:3}, // props的函数写法,作用:把返回的对象中每一组key-value作为props传给Detail组件props(route){return route.query}
}
① 对应props的布尔值写法(把收到了每一组【params参数】,作为props传给Detail组件):
News.vue
<li v-for="news in newsList" :key="news.id"><!-- 字符串写法 --><RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`">{{ news.title }}</RouterLink>
</li>
Detail.vue
<template><ul class="news-list"><li>编号:{{ id }}</li><li>标题:{{ title }}</li><li>内容:{{ content }}</li></ul>
</template><script setup lang="ts" name="About">defineProps(['id','title','content'])
</script>
② 对应props的函数写法
{name:'xiang',path:'detail/:id/:title/:content',component:Detail,props(route){return route.query}
}
Detail.vue
<template><ul class="news-list"><li>编号:{{ id }}</li><li>标题:{{ title }}</li><li>内容:{{ content }}</li></ul>
</template><script setup lang="ts" name="About">defineProps(['id','title','content'])
</script>
之前在父组件Father.vue 中注册使用子组件Son.vue(一般组件),可以直接在父组件内传递参数,<Son a="123">
于是在Son.vue中使用 defineProps接收参数。
但是如果是路由组件,其并不在父组件中注册,而是通过路由切换组件,这是就可以用到 本小节的路由规则的props配置。在路由组件中也用defineProps接收参数。
replace属性
-
作用:控制路由跳转时操作浏览器历史记录的模式。
-
浏览器的历史记录有两种写入方式:分别为
push
和replace
:push
是追加历史记录(默认值)。replace
是替换当前记录。
-
开启
replace
模式:<RouterLink replace .......>News</RouterLink>
编程式导航
之前我们路由跳转的时候,使用的是routerlink和routerview。最终浏览器会把 RouterLink 标签变为认识的 a 标签。但如果我们想要点击按钮跳转,怎么实现?
什么叫编程式路由导航?脱离 routerlink 实现路由跳转。
路由组件的两个重要的属性:$route
和$router
变成了两个hooks
import {useRoute,useRouter} from 'vue-router'const route = useRoute()
const router = useRouter()console.log(route.query)
console.log(route.parmas)
console.log(router.push)
console.log(router.replace)
- 示例
import {useRouter} from 'vue-router'
const router = useRouter()
router.push('/news')
这里的 push 写法,和routerlink中的to写法一样,有字符串写法、也有对象写法
router.push({path: '/news/detail',query: {id: news.id,title:news.title,content:news.content}
})
利用接口进行限制
import {useRouter} from 'vue-router'const router = useRouter()// 利用接口进行限制interface NewsInter {id:string,title:string,content:string} function showNewsDetail(news:NewsInter) {router.push({name: 'xiangqing',query: {id: news.id,title: news.title,content: news.content}})}
注意,在vue2中,编程式路由导航重复跳转是报错的。vue3中不算错。
- 使用场景
只有满足了某种条件之后,才会跳转路由。比如广告五秒之后跳转页面。
重定向
-
作用:将特定的路径,重新定向到已有路由。
-
具体编码:
{path:'/',redirect:'/about' }