Vue组件:Vue Router以及路由守卫,含路由的基本使用,配置,路由传参,导航方式,缓存;路由守卫的三种用法
Vue Router
vue-router
是 vue.js 官方给出的路由解决方案
。它只能结合 vue 项目进行使用,能够轻松的管理 SPA 项目中组件的切换。点击页面的导航链接时,不会刷新页面,只会局部更新
基础使用
使用步骤:
-
安装vue-router,命令
npm i vue-router@3.2.0
-
在src同级目录下创建router目录,并创建路由的js配置文件,index.js
-
创建组件(多个)
Home组件
<template> <div> <h1>我是Home组件</h1> </div> </template> <script> export default { name: "Home" } </script>
About组件
<template> <div> <h1>我是About组件</h1> </div> </template> <script> export default { name: "About" } </script>
-
编写路由的配置文件index.js
'/'
:默认展示页面// 1.引入路由的核心库 import VueRouter from "vue-router"; // 2.引入要被路由的组件 import Home from "@/components/Home"; import About from "@/components/About"; // 3.创建并暴露路由 export default new VueRouter({ routes:[ { path:'/', component:Home }, { path:'/about', component:About }, { path:'/home', component:Home } })
-
在main.js配置路由
import Vue from 'vue' import App from './App.vue' // 引入路由核心库 import VueRouter from "vue-router"; // 引入路由配置文件 import router from './router/index'; Vue.config.productionTip = false Vue.use(VueRouter) new Vue({ render: h => h(App), router // vue加载路由 }).$mount('#app')
-
在App.vue中注册组件,并使用
<template> <div id="app"> <router-link to="/home">Home</router-link> <router-link to="/about">About</router-link> <hr/> <!-- 准备被路由组件显示的位置--> <router-view></router-view> </div> </template> <script> export default { name: 'App', components: { } } </script>
多级路由
组件中包含组件,形成组件之间的嵌套,路由之间形成层级关系
-
创建组件,eg:News组件和Message组件
News组件:
<template> <div> <ul> <li>唱歌</li> <li>跳舞</li> <li>篮球</li> </ul> </div> </template> <script> export default { name: "News" } </script>
Message组件:
<template> <div> <ol> <li> <a href="#">测试数据1</a> </li> <li> <a href="#">测试数据2</a> </li> <li> <a href="#">测试数据3</a> </li> </ol> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message" } </script>
-
更改路由组件的配置,在父组件的路由下配置子组件路由
注意:二级路径不加
/
// 引入路由的核心库 import VueRouter from "vue-router"; // 引入要被路由的组件 import Home from "@/components/Home"; import About from "@/components/About"; import News from "@/components/News"; import Message from "@/components/Message"; import Detial from "@/components/Detail"; // 创建并暴露路由 export default new VueRouter({ routes:[ { path:'/', component:Home }, { path:'/about', component:About }, { path:'/home', component:Home, children:[ { path:'news', /* 二级路径不写/ */ component:News }, { path:'message', component:Message } ] } ] })
-
父组件中展示内容,父组件Home
多级路由跳转要写全路径
<template> <div> <h1>我是Home组件</h1> <router-link to="/home/news">News</router-link> <router-link to="/home/message">Message</router-link> <hr/> <!-- Home组件中路由显示的位置 --> <router-view></router-view> </div> </template> <script> export default { name: "Home" } </script>
路由组件传参
加入现在Message组件要给它的子组件Detail组件传参
-
路由配置文件中配置
// 引入路由的核心库 import VueRouter from "vue-router"; // 引入要被路由的组件 import Home from "@/components/Home"; import About from "@/components/About"; import News from "@/components/News"; import Message from "@/components/Message"; import Detial from "@/components/Detail"; // 创建并暴露路由 export default new VueRouter({ routes:[ { path:'/', component:Home }, { path:'/about', component:About }, { path:'/home', component:Home, children:[ { path:'news', /* 二级路径不写/ */ component:News }, { path:'message', component:Message, children:[ { path:'detail', component:Detial } ] } ] } ] })
-
Message组件传递
方式1:
使用模板字符串,并且给to属性添加
:
,拼接url,${}
的形式带参<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <router-link :to="`/home/message/detail? id=${msg.id}&title=${msg.title}`">{{msg.title}}</router-link> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } } } </script>
方式2:
改为对象形式的传参
<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <router-link :to="{ path:'/home/message/detail', query:{ id:msg.id, title:msg.title } }" > {{msg.title}} </router-link> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } } } </script>
-
Detail子组件中接收数据
使用
$route
属性,因为参数在url中所以要使用query
,再.
上参名即可传参<template> <div> <ul> <li>消息编号:{{$route.query.id}}</li> <li>消息标题:{{$route.query.title}}</li> </ul> </div> </template> <script> export default { name: "Detail" } </script>
命名路由
跳转时路径较长,使用命名路由简化跳转路径
实现步骤:
-
在路由配置中,给路由添加一个name属性,index.js
例如上述案例中给Detail组件添加一个命名路由,detail的路由配置如下
{ path:'message', component:Message, children:[ { path:'detail', name:'xq', // 添加命名 component:Detial } ] }
-
组件使用对象形式的跳转
使用name属性进行跳转
<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <router-link :to="{ // path:'/home/message/detail', name:'xq', // 用name属性跳转 query:{ id:msg.id, title:msg.title } }" > {{msg.title}} </router-link> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } } } </script>
路由的params参数
作用:路由之间进行参数传递,因此url中的参数名
实现步骤:
-
在路由配置中添加占位符,index.js中
{ path:'message', component:Message, children:[ { path:'detail/:id/:title', name:'xq', component:Detial } ] }
给path添加占位符,
:参数名
-
改变传参对象,query传参改为params传参,Message组件
使用params传参
情况1:对象形式
<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <router-link :to="{ name:'xq', // 用name属性跳转 params:{ id:msg.id, title:msg.title } }" > {{msg.title}} </router-link> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } } } </script>
情况2:字符串形式路径
<router-link :to="`/home/message/detail/${msg.id}/${msg.title}`"> {{msg.title}} </router-link>
-
改变数据接收,query接收改为params接收,Detail组件
使用params接收
<template> <div> <ul> <li>消息编号:{{$route.params.id}}</li> <li>消息标题:{{$route.params.title}}</li> </ul> </div> </template> <script> export default { name: "Detail" } </script>
props配置
作用:简化接收参数
实现步骤:
-
路由配置中配置props属性
方式一:固定值方式
props:{id:xxx,titel:...}
方式二:启用方式
{ path:'message', component:Message, children:[ { path:'detail/:id/:title', name:'xq', component:Detial, props:true // 启用方式 } ] }
方式三:决定来源的方式
{ path:'message', component:Message, children:[ { path:'detail/:id/:title', name:'xq', component:Detial, props($route){ return { id : $route.params.id, //params/query 取决于来源于哪 title : $route.params.title } } } ] }
-
传参组件中params传参
<router-link :to="{ name:'xq', // 用name属性跳转 params:{ id:msg.id, title:msg.title } }" > {{msg.title}} </router-link>
-
接收组件中添加props接收,通过插值表达式使用
<template> <div> <ul> <li>消息编号:{{id}}</li> <li>消息标题:{{title}}</li> </ul> </div> </template> <script> export default { name: "Detail", props:['id','title'] } </script>
浏览器历史记录的两种写入模式
在Home组件中添加前进后退按钮
<template>
<div>
<h1>我是Home组件</h1>
<router-link to="/home/news">News</router-link>
<router-link to="/home/message">Message</router-link>
<button @click="back">后退</button>
<button @click="forward">前进</button>
<hr/>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "Home",
methods:{
back(){
this.$router.back(); // $router : main.js中的名字
},
forward(){
this.$router.forward();
}
}
}
</script>
在Message组件中添加模式
<!-- 可以写push 或者 replace 模式 -->
<router-link push :to="{
// path:'/home/message/detail',
name:'xq',
params:{
id:msg.id,
title:msg.title
}
}" >
{{msg.title}}
</router-link>
-
push:追加历史记录
记录历史记录,一步一步回退
-
replace:替换当前历史记录
不保留历史记录,直接退回上个路由
导航方式
-
声明式
上例中浏览器的写入模式演示的就是声明式的导航方式
<!-- 可以写push 或者 replace 模式 --> <router-link push :to="{ // path:'/home/message/detail', name:'xq', params:{ id:msg.id, title:msg.title } }" > {{msg.title}} </router-link>
-
编程式
编程式绑定事件,传参通过()方式传递,方法中可以采用push或replace方式,方法中给一个配置对象,跳转地址,参数等
<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <button @click="goDetail(msg.id,msg.title)">{{msg.title}}</button> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } }, methods:{ goDetail(id,title){ this.$router.push({ name:'xq', params:{ id:id, title:title } }) } } } </script>
缓存
-
News组件中有输入框
<template> <div> <ul> <li>唱歌 <input type="text"></li> <li>跳舞 <input type="text"></li> <li>篮球 <input type="text"></li> </ul> </div> </template> <script> export default { name: "News" } </script>
-
Message组件有输入框
<template> <div> <ol> <li v-for="msg in msgList" :key="msg.id"> <button @click="goDetail(msg.id,msg.title)">{{msg.title}}</button> <input type="text"> </li> </ol> <hr/> <router-view></router-view> </div> </template> <script> import {nanoid} from 'nanoid'; export default { name: "Message", data(){ return{ msgList:[ {id:nanoid(),title:'消息数据A'}, {id:nanoid(),title:'消息数据B'}, {id:nanoid(),title:'消息数据C'} ] } }, methods:{ goDetail(id,title){ this.$router.push({ name:'xq', params:{ id:id, title:title } }) } } } </script>
-
想要输入框的输入内容在跳转组件之后仍存在,需要给Home.vue父组件添加缓存
<template> <div> <h1>我是Home组件</h1> <router-link to="/home/news">News</router-link> <router-link to="/home/message">Message</router-link> <hr/> <keep-alive> <router-view></router-view> </keep-alive> </div> </template> <script> export default { name: "Home" } </script>
用
<keep-alive></keep-alive>
标签包裹<router-view></router-view>
指定组件缓存:
include="指定缓存组件的组件名"
<keep-alive include="News"> <router-view></router-view> </keep-alive>
指定多组件缓存:
:include="['组件名','组件名'...]"
<keep-alive :include="['News','Message']"> <router-view></router-view> </keep-alive>
在缓存的组件中添加缓存激活/失活生命周期函数
激活状态:activated(){}
失活状态:deactivated(){}
eg:News组件
<template>
<div>
<ul>
<li>唱歌 <input type="text"></li>
<li>跳舞 <input type="text"></li>
<li>篮球 <input type="text"></li>
</ul>
</div>
</template>
<script>
export default {
name: "News",
activated() {
console.log("组件激活")
},
deactivated() {
console.log("组件失活")
}
}
</script>
路由守卫
类似于过滤器的作用
全局路由守卫
全局路由守卫 :全部的路由都会执行
-
前置路由守卫
路由配置文件中配置路由守卫,将创建路由对象,并配置路由守卫,最后将路由对象暴露
// 引入路由的核心库 import VueRouter from "vue-router"; // 引入要被路由的组件 import Home from "@/components/Home"; import About from "@/components/About"; import News from "@/components/News"; import Message from "@/components/Message"; import Detial from "@/components/Detail"; // 创建并暴露路由 const router = new VueRouter({ routes:[ { path:'/', component:Home }, { path:'/about', component:About }, { path:'/home', component:Home, children:[ { path:'news', /* 二级路径不写/ */ component:News }, { path:'message', component:Message, children:[ { path:'detail/:id/:title', name:'xq', component:Detial, props:true } ] } ] } ] }) // 全局路由守卫 // 1.前置路由守卫 // 箭头函数三个参数,to:去哪里 from:从哪里来 next:执行next()才放行,不执行则拦截 router.beforeEach((to, from, next)=>{ console.log(to,from); next(); }) export default router;
-
后置路由守卫
// 2.后置路由首位 // 箭头函数两个参数,to:去往哪里 from:从哪里来 router.afterEach((to, from)=>{ console.log(to); console.log(from); })
独享路由守卫
针对于某个路由的守卫,再路由配置中添加独享路由守卫,例如给detail添加独享守卫
// 引入路由的核心库
import VueRouter from "vue-router";
// 引入要被路由的组件
import Home from "@/components/Home";
import About from "@/components/About";
import News from "@/components/News";
import Message from "@/components/Message";
import Detial from "@/components/Detail";
// 创建并暴露路由
const router = new VueRouter({
routes:[
{
path:'/',
component:Home
},
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news', /* 二级路径不写/ */
component:News
},
{
path:'message',
component:Message,
children:[
{
path:'detail/:id/:title',
name:'xq',
component:Detial,
props:true,
// 独享路由守卫
beforeRouteEnter(to,from,next){
console.log(to);
console.log(from);
next();
}
}
]
}
]
}
]
})
export default router;
组件路由守卫
组件内部的路由守卫
- 前置路由守卫
- 后置路由守卫,与全局路由守卫不同的是后置路由守卫有next()方法
<template>
<div>
<h1>我是About组件</h1>
</div>
</template>
<script>
export default {
name: "About",
beforeRouteEnter(to,from,next){
//组件前置路由守卫
console.log(to);
console.log(from);
next(); // 执行放行
},
beforeRouteLeave(to,from,next){
//组件后置路由守卫
console.log(to);
console.log(from);
next(); // 组件后置路由守卫执行next()方法才会出去
}
}
</script>
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!