路由
Vue实质上是一个 SPA(单Web应用程序) 应用,也就是实质上其实只有一张页面。所以我们使用route进行切换。
基本构成:
1、导航区、展示区
2、路由器
3、制定路由的具体规则(什么路径,对应着什么组件)
4、形成 一个一个的 xxx.vue 文件
5、告诉路由把命中的组件放在哪里:RouterView
6、不要通过直接在浏览器输入路由,通过:RouterLink
基本的切换效果
1、安装路由
npm install vue-router
2、创建路由器并暴露
对应位置:src/router/index.ts
//### 创建一个路由器,并暴露出去 ###
import { createRouter, createWebHashHistory } from "vue-router"; //引入createRouter
//以下是需要呈现的组件
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";
import News from "@/components/News.vue";
//创建路由器
const router = createRouter({
history: createWebHashHistory(), //路由器的工作模式
routes: [ //一个一个的路由规则
{
path: '/home',
component: Home
},
{
path: '/about',
component: About
},
{
path: '/news',
component: News
}
]
})
export default router; //暴露出去router
3、创建对应的路由组件
4、创建了路由器实例,并将其注册为插件
位于:/src/main.ts
// 引入createApp用于创建应用
import { createApp } from "vue";
// 引入App根组件
import App from "./App.vue";
// 引入路由器
import router from "./router";
const app = createApp(App);
app.use(router);
app.mount("#app");
5、设置对应显示的位置
<div class="main-content">
<!-- 呈现对应组件 -->
<RouterView></RouterView>
</div>
6、点击后进行路由切换
这样就不用手动输入路由路径了,当然这里还通过属性设置了选中后的样式。
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/home" active-class="active">首页</RouterLink>
<RouterLink to="/news" active-class="active">新闻</RouterLink>
<RouterLink to="/about" active-class="active">关于</RouterLink>
</div>
路由组件放置位置与切换后卸载组件
为了区分路由组件和一般组件,路由组件通常存放在pages
或 views
文件夹,一般组件通常存放在components
文件夹。
通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。编写对应生命周期即可查看。
to的两种写法
<!-- 第一种:to的字符串写法 -->
<RouterLink to="/home" active-class="active">首页</RouterLink>
<!-- 第二种:to的对象写法 -->
<RouterLink :to="{path: '/about'}" active-class="active">关于</RouterLink>> <!-- 通过路由 -->
<RouterLink :to="{name: 'news'}" active-class="active">新闻</RouterLink> <!-- 通过命名 -->
路由的工作模式
history模式
写法:
Vue2:mode:'hsitory'
Vue3: history:createWebHistory()
React: BrowserRouter
优点:URL
更加美观,不带有#
,更接近传统的网站URL
。
缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404
错误。
参考代码:
const router = createRouter({
history:createWebHistory(), //history模式
/******/
})
补充(因为hash模式不会把#后面的路径给到对应服务端所以用特殊处理,因为SPA):
# 参考nginx简单处理方案
location / {
try_files $uri $uri/ /index.html;
}
hash模式
优点:兼容性更好,因为不需要服务器端处理路径。
缺点:URL
带有#
不太美观,且在SEO
(搜索引擎优化)优化方面相对较差。
参考代码:
const router = createRouter({
history:createWebHashHistory(), //hash模式
/******/
})
命名路由
作用:可以简化路由跳转及传参(后面就讲)。
给路由规则命名:
routes: [ //一个一个的路由规则
{
name:'home',
path: '/home',
component: Home
},
{
name:'about',
path: '/about',
component: About
},
{
name:'news',
path: '/news',
component: News
}
]
<!-- 命名后,对象写法就可以通过命名来,如/news/xxx路由也可以简化命名书写 -->
<RouterLink :to="{name: 'news'}" active-class="active">新闻</RouterLink> <!-- 通过命名 -->
嵌套路由
这里步骤中不再包含一些必要的如安装路由,use到App的操作了。
编写嵌套路由
routes: [ //一个一个的路由规则
{
name:'home',
path: '/home',
component: Home
},
{
name:'about',
path: '/about',
component: About
},
{
name:'news',
path: '/news',
component: News,
children: [
{
path: 'detail', //子级前面不用加/
component: Detail
}
]
}
]
编写对应路由组件
<template>
<ul class="news-list">
<li>编号:xxx</li>
<li>标题:xxx</li>
<li>内容:xxx</li>
</ul>
</template>
<script setup lang="ts" name="Detail">
</script>
<style scoped>
.news-list {
list-style: none;
padding-left: 20px;
}
.news-list>li {
line-height: 30px;
}
</style>
使用
<template>
<div class="news">
<!-- 导航区 -->
<ul>
<li v-for="news in newsList" :key="news.id">
<RouterLink to="/news/detail"> {{ news.content }} </RouterLink>
<!-- <RouterLink :to="{path: '/news/detail'}"> {{ news.content }} </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'
const newsList = reactive([
{id:'asfdtrfay01',title:'很好的抗癌食物',content:'西蓝花'},
{id:'asfdtrfay02',title:'如何一夜暴富',content:'学IT'},
{id:'asfdtrfay03',title:'震惊,万万没想到',content:'明天是周一'},
{id:'asfdtrfay04',title:'好消息!好消息!',content:'快过年了'}
])
</script>
<style scoped>
/* 新闻 */
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
height: 100%;
}
.news ul {
margin-top: 30px;
/* list-style: none; */
padding-left: 10px;
}
.news li::marker {
color: #64967E;
}
.news li>a {
font-size: 18px;
line-height: 40px;
text-decoration: none;
color: #64967E;
text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
width: 70%;
height: 90%;
border: 1px solid;
margin-top: 20px;
border-radius: 10px;
}
</style>
路由传参(重点)
query参数
1、在导航区点击时通过query传递参数:
<!-- 导航区 -->
<ul>
<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> -->
<!-- 第二种写法 -->
<RouterLink
:to="{
name: 'detail',
query: {
id: news.id,
title: news.title,
content: news.content
}
}"
>
{{ news.title }}
</RouterLink>
</li>
</ul>
2、对应的路由组件接收参数
<script setup lang="ts" name="Detail">
import { useRoute } from 'vue-router'; // 从命名中可以看出 这是已给hooks
import { toRefs } from 'vue';
let router = useRoute();
// console.log('查看', router);
let { query } = toRefs(router); //从响应式中解构属性会失去响应式
console.log('查看是否为响应式:', query);
</script>
params参数
1、先配置路由
routes: [ //一个一个的路由规则
{
name:'home',
path: '/home',
component: Home
},
{
name:'about',
path: '/about',
component: About
},
{
name:'news',
path: '/news',
component: News,
children: [
{
name: 'detail',
path: 'detail/:id/:title/:content?', //子级前面不用加 ? 表示可传可不传
component: Detail
}
]
}
]
2、在导航区点击时通过params传递参数:
<ul>
<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: 'detail', //必须使用name
params: { //参数不能是对象和数组
id:news.id,
title:news.title,
content:news.content,
}
}"
>
{{ news.title }}
</RouterLink>
</li>
</ul>
3、接收参数
<script setup lang="ts" name="Detail">
import { useRoute } from 'vue-router';
import { toRefs } from 'vue';
const route = useRoute();
// console.log(route);
let { params } = toRefs(route);
console.log(params);
</script>
注意事项
备注1:传递params
参数时,若使用to
的对象写法,必须使用name
配置项,不能用path
。
备注2:传递params
参数时,需要提前在规则中占位。
备注3:传递params
参数时,不能传递对象或数组参数。
路由_props配置
作用:让路由组件更方便的收到参数(可以将路由参数作为props
传给组件),这样可以简化接收位置的书写,只是需要注意三种写法,第一种适用于写了params的方式,第二种query和params都可以,第三种写的较死。
参考代码:
children: [
{
name: 'detail',
path: 'detail/:id/:title/:content?', //子级前面不用加 ? 表示可传可不传
component: Detail,
//### 第一种写法:将路由收到的所有params参数作为props传给路由组件
// props: true //从<Detail> --> <Detail id = ?? title = ?? content = ??>
//### 第二种写法:函数写法,可以自己决定将什么作为props给路由组件
// props(arg) { //这个参数就是路由参数,可以获取params或者query,一般用于处理query,毕竟params有上面的写法
// return arg.params;
// }
//### 第三种写法:对象写法,可以自己决定将什么作为props给路由组件
props: { //有点写死了
a: 100,
b: 200,
c: 300
}
}
]
推荐
1、使用query参数的时候用第二种写法
props(arg) {
return arg.query;
}
2、使用params参数的时候用第一种写法
{
name: 'detail',
path: 'detail/:id/:title/:content?', //子级前面不用加 ? 表示可传可不传
component: Detail,
props: true
}
3、第三种写法可以用于一些较为固定的地方
{
name: 'detail',
path: 'detail/:id/:title/:content?', //子级前面不用加 ? 表示可传可不传
component: Detail,
props: { //有点写死了
a: 100,
b: 200,
c: 300
}
}
replace属性
作用:控制路由跳转时操作浏览器历史记录的模式。
浏览器的历史记录有两种写入方式:分别为push
和replace
:
push
是追加历史记录(默认值)。
replace
是替换当前记录。
开启replace
模式(在对应的 RouterLink 中加上属性后就可以设置,然后点击这个后就无法使用浏览器回退):
<RouterLink replace .......>...</RouterLink>
路由_编程式路由导航(脱离 RouterLink 实现路由跳转)
使用编程式路由导航,我们可以脱离 RouterLink进行路由跳转,无论是点击按钮、鼠标滑过、定时跳转如跳到秒杀页面等场景都可以使用。关键在于:学了to,我们通过获取路由器进行跳转中如使用 push 的方式也可以接受字符串或者对象,所以可以直接用to写法的格式
参考代码:
function showNewsDetail(news:NewsInter) { //可以写 :any 跳过检查
//### 这里push可以接收的对象是字符串 或者 对象,所以可以直接使用to的写法
router.push({ //这里也可以使用一个 replace 就不能使用浏览器回退了
name: 'detail', //必须使用name
params: { //参数不能是对象和数组
id:news.id,
title:news.title,
content:news.content,
}
});
}
路由_重定向
如做初始跳转:
{
path:'/',
redirect: '/home'
}
标签:name,component,router,news,path,路由
From: https://www.cnblogs.com/fragmentary/p/18626706