路由
路由就是一组key value 的对应关系,多个路由,需要经过路由器的管理
路由环境简单的切换效果(步骤)
切换的标题为导航组件(pages/views文件夹中 ***.vue),把定义的组件引入到路由(router文件夹)中,path路径随便起名。
在需要使用的页面结构中定义两个区域,分别为导航区和展示区,展示区随着导航区的单击切换展示区的内容
但是需要在使用的页面中,从vue-router中引入RouterView,把引入RouterView写成标签放在展示区域
还需要从从vue-router中引入RouterLink,把导航区域的每个标题用RouterLink包裹起来,
然后在RouterLink的to属性后面添加上在路由文件夹中定义的path路径,active-class="标题高亮"。标题高亮是样式。
<div class="nav">
//to: 字符串写法
<RouterLink to="/home" active-class="active">首页</RouterLink>
<RouterLink to="/video" active-class="active">视频</RouterLink>
to的另一种写法对象写法,如果在路由中配置了name属性,那么把name放在对象,也可以正常跳转
<RouterLink :to="{path:'/home'}" active-class="active">首页</RouterLink>
<RouterLink :to="{ path:'/video'}" active-class="active">视频</RouterLink>
</div>
<div class="conent">
<RouterView />
</div>
路由组件通常放在pages或view文件夹,一般组件通常放在components文件夹,:靠路由的规则渲染出来的
通过点击导航,视觉效果上"消失"了的路由组件,默认是被销毁掉的,需要的时候再去挂载
一般组件:亲手书写的标签的形式
路由的模式
1、history模式
vue2:mode: 'history'
vue3: history: createWebHistory()
优点:URL更加美观,不带有#,更接近传统的网站URL。
缺点:后期项目上线,需要服务端配合处理路劲问题,否则刷新会有404错误。
const router=createRouter({
history:createRouter(),
})
2、hash模式
vue2:mode: 'hash'
vue3: history: createWebHashHistory()
需要引入import {createWebHashHistory} from 'vue-router'
优点:兼容性更好,因为不需要服务端处理路径
缺点:URL带有#不太美观,且在seo优化方面相对较差。
const router=createRouter({
history:createWebHashHistory()
})
路由嵌套
{
path: '/index',
component: () => import('../views/Index/index.vue'),
children: [
{
path: '/index/main',
component: () => import("../views/Index/Main/index.vue")
},
{
path: '/user/list',
component: () => import("../views/user/list.vue")
},
{
path: '/user/message',
component: () => import("../views/user/message.vue")
},
]
}
路由传参 query
query 传参时路由指向 既可以使用path也可以使用name
`` 模板字符串 news 是通过v-for循环的每一项
1、 里面的path也可以写成name(name的前提是在路由表中要有这个属性)
<Router-Link :to="`/news/detail?id=${news.id}&${news.title}`"></Router-Link>
第二种写法
<router-link
:to="{
path:'/news/detail',
query:{
id:news.id,
title:news.title
}
}"
>
</router-link>
目标页
需要从vue身上解构useRoute
import {useRoute} from 'vue-router';
let route=useRoute()
console.log(route.query) //打印query传递的参数
页面渲染就是
<li>{{route.query.id}}</li>
要想使渲染的层级不是很深
可以利用toRefs
import { toRefs } from 'vue';
import {useRoute} from 'vue-router';
let route=useRoute()
let { query } = toRefs(route)
页面渲染就是
<li>{{query.id}}</li>
路由传参 params 只能用name
使用params传递参数时,若使用to的对象写法,必须使用name配置项,不能用path
使用params传递参数时,需要提前在路由规则中占位
需要在路由文件里面占位(下面的路由时子集路由的部分)
{
path:'detail/:id/:title',
component:Detail
}
注意:在传的参数后面加问号,表示这个参数可传,也可不传
第一种写法
<Router-Link :to="`/news/detail/${news.id}/${news.title}`"></Router-Link>
第二种写法
<router-link
:to="{
name:'/news/detail',
params:{
id:news.id,
title:news.title
}
}"
>
</router-link>
注意:params中的参数,必须与路由中的占位必须一致
目标页
需要从vue身上解构useRoute
import {useRoute} from 'vue-router';
let route=useRoute()
页面渲染就是
<li>{{route.params.id}}</li>
路由文件夹下index.ts props的三种写法
{
name:'xiang',
path:'detail/:id/:title',
component:Detail
}
第一种布尔值写法 将路由收到的所有的params参数作为props传给路由;
props:true
第二种函数写法 可以将自己决定将什么作为props给路由组件
props(route){
console.log(route) // 这里的route是路由信息
return route.query
}
第三种对象写法 把对象中的每一组key-value作为props传给detail组件
}
页面渲染就是
<li>{{id}}</li>
<script setup lang="ts"> defineProps(['id','title'])</script>
replace属性
作用: 控制路由跳转时操作浏览器历史记录的模式
浏览器的历史记录有两种写入方式:分别为push和replace
push 是追加历史记录(默认值) 可以回退
replace 是替换当前记录。 不可以回退
开启replace 模式:
<RouterLink replace.....> about </RouterLink>
编程式导航
RouterLink 最终编译成a标签,所以有时候会需要用到编程式导航
import {useRouter} from 'vue-router';
const router=useRouter()
function showDetail(news){
router.push({ //这里用replace的话,就不能后退
name:'detail',
query:{
id:news.id,
title:news.title
}
})
}
在ts文件中需要对news定义类型
news:any
interface NewsInter{
id:string,
title:string
}
news:NewsInter
在页面中
<button @click="showDetail(news)"></button>
redirect重定向
{
path:'/',
redirect:'/about'
}
就类似于银行窗口办理业务,你本是普通用户,但是你去了vip窗口,VIP里面的工作人员说,你要去普通用户窗口办理
路由守卫
作用
对路由进行权限控制,以达到保护路由的目的
分类
全局前置路由守卫(用的最多)
router.beforeEach((to, from, next) => {
let token = localStorage.getItem('token');
if (to.fullPath != '/login' && !token) {
router.push('/login');
return false
} else {
next()
}
})
无感登录守卫
登录页面
const onSubmit = async () => {
let name = form.name;
let password = form.password;
let res = await login({ name, password });
console.log(res, 1234543212345543)
if (res.data.msg == 'ok') {
var date=new Date();
//这里是2个小时有效期 expiress 后面也可以跟数字,数字代表天数
var expires=date.getTime()+2*60*60*1000;
Cookies.set('token',res.data.token,{expires:expires})
ElMessage({
message: '登录成功',
type: 'success',
})
router.push('/home/touq')
} else {
ElMessage({
message: '登录失败,账号或密码有误',
type: 'warning',
})
}
}
//路由守卫
import Cookies from 'js-cookie';
router.beforeEach((to, from, next) => {
let token=Cookies.get('token')
if (to.fullPath !== '/login') {
if (!Cookies.get('token')) {
router.push('/login');
return
} else {
next()
}
} else {
router.push('/login');
}
})
全局后置路由守卫,
独享式路由守卫
组件路由守卫
全局路由守卫:一旦定义好路由守卫,全部的路由都可以使用
过度动画
1、官网:
https://cn.vuejs.org/guide/built-ins/transition.html
2、代码
<Transition>
<p v-if="show">hello</p>
</Transition>
css
/* 下面我们会解释这些 class 是做什么的 */
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
404页面
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound },