6.前端路由 router
Vue Router | Vue.js 的官方路由 (vuejs.org)
官方地址 : https://router.vuejs.org/zh/
6.1.基本配置
6.1.0.准备 MyPage.vue
创建 用于测试 vue文件 ../views/MyPage.vue
vue
<template>
<div>
<h1>MyPage</h1>
</div>
</template>
<script >
</script>
<style scoped lang="scss">
</style>
6.1.1.基本配置
src / router / index.js 路由文件
js
const routes = [
{
path: '请求路径',
name: '名称',
component: 对应组件, 需要引入组件
},
...
]
如果想引入新的资源, 写好First.vue 文件
先在 src / router / index.js 路由文件中添加引入组件
js
// 引入 组件
import MyPage from '../views/MyPage.vue'
再增加 路由信息
js
{
path: '/myPage',
name: 'myPage',
component: MyPage,
},
6.1.2.导航标签/显示标签
<router-link to="/path" >说明</router-link>
导航标签, 相当于html中的 <a>
, 其中的 to 属性 相当于 href 属性
<router-view></router-view>
显示标签, 相当于 html中的 <iframe>
用于显示
在 App.vue 页面中应用
html
<template>
<div id="app">
<!-- 导航, router-link 相当于<a> to属性 相当于 href -->
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/myPage">MyPage</router-link>
</div>
<!-- 显示区, 根据导航显示不同的内容 -->
<router-view></router-view>
</div>
</template>
6.2.子路由(多级路由/嵌套路由)
6.2.1.创建两个vue文件
在 src / views 中添加 两个 vue 文件
/views/Page1.vue
Page1.vue
vue
<template>
<div>
<h1>page1</h1>
</div>
</template>
<script >
</script>
<style scoped lang="scss">
</style>
/views/Page1.vue
Page2.vue
vue
<template>
<div>
<h1>page2</h1>
</div>
</template>
<script >
</script>
<style scoped lang="scss">
</style>
6.2.2.配置子路由
修改 src / router / index.js 路由文件中添加引入组件
js
import Page1 from '@/views/Page1.vue'
import Page2 from '@/views/Page2.vue'
修改 路由配置, 增加 children
属性 ,
注意 子路由配置 path 时, 前面没有 / 斜杠
page1
,page2
也可以 写 全路径
/myPage/page1
,/myPage/page2
js
{
path: '/myPage',
name: 'myPage',
component: MyPage,
children:[
{
path: 'page1',
name: 'Page1',
component: Page1,
},
{
path: 'page2',
name: 'Page2',
component: Page2,
}
]
},
6.2.3.修改 MyPage.vue 文件
在 MyPage.vue 文件中
增加 用于路由跳转的 <router-link></router-link>
及用于显示的 <router-view></router-view>
vue
<template>
<div>
<h1>MyPage</h1>
<div >
<div style="float: left; width: 200px; height: 500px; background: aliceblue;">
<div id="nav">
<router-link to="/myPage/page1" active-class="active">页面1</router-link>
<br/> <br/>
<router-link to="/myPage/page2" active-class="active">页面2</router-link>
</div>
</div>
<div style="float: left; width: 800px; height: 500px; background: #eeeeee; border-radius: 5px;" >
<router-view></router-view>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.active {
color: red;
}
</style>
6.3.相关概念
6.3.1.两种工作模式
在 Vue.js 中,Vue Router 提供了两种不同的路由模式:hash 和 history。
6.3.1.1.Hash 模式:
-
当使用 hash 模式时,URL 的路径部分会包含一个
#
(哈希)符号,以及随后的路由标识符。例如,http://example.com/#/user/home
。 -
#
(哈希)符号 后面的内容不会在请求时发给服务器 -
浏览器通过监听
hashchange
事件来检测 URL 哈希值的变化,并且由于哈希变化不会导致页面重新加载,所以这种模式对旧版浏览器兼容性较好。 -
在 Vue Router 中配置为 hash 模式的方法是:
javascriptconst router = new VueRouter({ mode: 'hash', routes: [...] });
6.3.1.2.History 模式:
-
History 模式利用 HTML5 History API 来实现 URL 路径的变化,这样生成的 URL 就像正常的页面 URL,没有
#
符号。例如,http://example.com/user/home
。 -
使用此模式时,当用户点击浏览器的前进、后退按钮或者直接修改地址栏中的 URL,Vue Router 可以监听到这些变化并作出相应调整。
-
然而,为了使服务器能够正确处理这些 URL 请求而不返回 404 错误,在部署应用时需要配置服务器,使其将所有未命中静态资源请求都指向应用的入口文件(通常是 index.html)。
-
在 Vue Router 中配置为 history 模式的方法是:
javascriptconst router = new VueRouter({ mode: 'history', routes: [...] });
总结来说,hash 模式简单易用,但 URL 显示不够优雅;history 模式提供更自然的 URL 结构,但需要额外的服务器端配置支持。
根据项目需求和开发环境选择合适的路由模式。
6.3.2.路由对象
route : 表示一条路由, 就是一组 标识 key ( 路径path ) 对应一组组件 component 或者 函数 function
-
route
对象表示当前活动的路由信息。当你导航到应用中的某个路径时,Vue Router 会解析这个 URL,并创建一个对应的route
对象。 -
这个对象包含了从 URL 解析出的详细信息,如:
path
(当前路由路径)、params
(动态路由参数)、query
(查询参数)、name
(命名路由的名字)等。 -
在 Vue 组件内部,可以通过
this.$route
访问当前活跃的route
对象。 -
routes
表示一组路由
6.3.3.路由器
router : 它是一个机制, 充当管理路由的管理者角色.
router
是一个全局可用的 Vue Router 实例,它是整个应用路由系统的管理者和控制中心。- 通过调用
Vue.use(VueRouter)
安装路由插件后,我们可以创建并配置一个router
实例,定义应用的所有路由规则以及他们的组件映射、嵌套路由、重定向、命名路由等功能。 - router 提供了许多方法来操纵应用程序的路由状态,比如:
router.push(location)
:将当前位置更改为给定的新位置。router.replace(location)
:类似于push
,但是不会向历史记录添加新条目。router.go(n)
:在浏览器的历史记录中向前或向后移动指定的步数。router.resolve(location)
:解析给定的位置,返回一个描述如何到达该位置的对象。
- 我们通常在 Vue 应用初始化阶段通过
new VueRouter()
创建router
实例,并将其注入到根 Vue 实例的router
属性上。 this.$router
表示全局路由器对象
6.3.4.vue文件分类
组件
: 在vue文件中 通过 import导入, 并使用 components 声明的 通常当成 组件, 存放在 components 文件中
页面
: 通过路由访问的vue文件通常当成页面, 存放在 views , pages 等文件夹中
6.4.路由传值
6.4.1.query方式
query方式,可以在地址栏可以看到参数 , 相当于url?传参
6.4.1.1.基本写法
在 /views/AboutView.vue
增加 两组 <router-link>
标签 ,
分别以 字符串及json 格式 进行传参
vue
<router-link to="/myPage?id=123&title=标题">MyPage query</router-link>
<br>
<router-link :to="{
path: '/myPage',
query: {
id: 123,
title: '标题'
}
}">MyPage query json</router-link>
在 /views/MyPage.vue
的 mounted 函数中通过 this.$route
接收传递来的值
js
mounted() {
console.log(this.$route)
}
可以在控制台 可以 看到 query打印 内容
js
fullPath: "/myPage?id=123&title=%E6%A0%87%E9%A2%98"
hash: ""
matched: [{...}]
meta: {}
name: "myPage"
params: {}
path: "/myPage"
query: {id: '123', title: '标题'}
[[Prototype]]: Object
6.4.1.2.传对象信息
在 /views/AboutView.vue
增加 data信息
dd 对象 , 包括 id, title 两个属性
js
data () {
return {
msg: 'Welcome to Your Vue.js App',
dd:{
id: 666,
title: '对象的标题'
}
}
}
在 template
中增加 新的 <router-link>
标签 ,
并使用`` 反引号` 进行 模板接值
html
<br>
<router-link :to="`/myPage?id=${dd.id}&title=${dd.title}`">MyPage query dd</router-link>
这样就可以传递动态信息
6.4.2.params
params方式, 在地址栏 看不到参数
但要 在路由的 index.js 文件中 path属性后面追加 :标识
用于设置传值的标识
6.4.2.0.准备MyPage2.vue
增加新的 /views/MyPage2.vue
文件
vue
<template>
<h1>MyPage2</h1>
</template>
<script >
export default {
name: 'MyPage2',
mounted() {
console.log(this.$route)
}
}
</script>
在路由的 index.js 文件中引入文件
js
import MyPage2 from '../views/MyPage2.vue'
增加路由配置, 在 路由后追加了 :id , :title
js
{
path: '/myPage2/:id/:title',
name: 'myPage2',
component: MyPage2,
},
6.4.2.1.基本写法
在 /views/AboutView.vue
增加 <router-link>
标签 ,
html
<br>
<router-link :to="`/myPage2/${dd.id}/${dd.title}`">MyPage2 params </router-link>
在 /views/MyPage2.vue
的 mounted函数中通过 this.$route
接收传递来的值
可以在控制台看到, params 接收到值
text
fullPath: "/myPage2?id=123&title=%E6%A0%87%E9%A2%98"
hash: ""
matched: [{...}]
meta: {}
name: "myPage2"
params: {id: '666', title: '对象的标题'}
path:"/myPage2/666/对象的标题"
query: {}
[[Prototype]]: Object
6.4.2.2.params 对象传值
在 /views/AboutView.vue
增加 <router-link>
标签 , 通过json 格式传值
这里要注意 在使用 params 传值时 , 要使用 name 来设置路由目标
html
<br>
<router-link :to="{
name: 'myPage2',
params: {
id: dd.id,
title: dd.title
}
}">MyPage2 params json</router-link>
6.4.3.props
在 路由的index.js 文件中 通过 props 来设置接值
6.4.3.0.准备MyPage3.vue
增加新的 /views/MyPage3.vue
文件
vue
<template>
<h1>MyPage3</h1>
</template>
<script >
export default {
name: 'MyPage3',
mounted() {
console.log(this.$route)
}
}
</script>
在路由的 index.js 文件中引入文件
js
import MyPage3 from '../views/MyPage3.vue'
增加路由配置, 在 路由后追加了 :id , :title
js
{
path: '/myPage3',
name: 'myPage3',
component: MyPage3,
},
6.4.3.1. 值为对象
该对象中的所有key-value都会以props的形式传给目标组件
修改路由index.js中的配置:
js
{
path: '/myPage3',
name: 'myPage3',
component: MyPage3,
props:{id:1,title:'hello'}
}
在 /views/MyPage3.vue
文件 增加 props 接值
vue
<template>
<div>
<h1>MyPage3</h1>
<h2>{{id}}</h2>
<h2>{{title}}</h2>
</div>
</template>
<script >
export default {
name: 'MyPage3',
props: ["id", "title"],
mounted() {
console.log(this.$route)
}
}
</script>
这种方式 只能接收到 配置文件中的固定值
6.4.3.2.值为布尔值
若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给目标组件。
修改路由index.js 文件 配置
js
{
path: '/myPage3/:id/:title',
name: 'myPage3',
component: MyPage3,
props:true
}
在 /views/AboutView.vue
增加 <router-link>
标签 ,
html
<br>
<router-link :to="`/myPage3/${dd.id}/${dd.title}`">MyPage3 params </router-link>
这里注意 只能 针对 params 传值 方式有效
6.4.3.3.值为函数
通过 函数参数进行传值 , 这时 对 query, params 参数 都可以转换成 props 信息
修改路由index.js 文件 配置
js
{
path: '/myPage3/:id/:title',
name: 'myPage3',
component: MyPage3,
props($route){
return {
id:$route.params.id,
title:$route.params.title,
}
}
}
6.5.编程式路由
编程式路由是指通过编程( js 代码 )的方式来操作和控制路由的跳转
6.5.1.push
this.$router.push(path)
: 该方法用于将当前历史记录推入一个新条目。调用 router.push
会将应用从当前路径跳转到指定的新路径。
6.5.1.1.基本跳转
在 /views/AboutView.vue
增加 <button>
按钮 并 增加事件
html
<br>
<button @click="goMyPagePush">转到 MyPage push</button>
在 methods 中增加处理函数
js
methods: {
goMyPagePush(){
this.$router.push('/myPage')
}
}
6.5.1.2.跳转query传值
在 /views/AboutView.vue
增加 <button>
按钮 并 增加事件
html
<br>
<button @click="goMyPagePush2">转到 MyPage push 2</button>
在 methods 中增加处理函数
js
goMyPagePush2(){
this.$router.push({
path: '/myPage',
query: {
id: 123,
title: '标题'
}
})
},
6.5.1.3.跳转params传值
在 /views/AboutView.vue
增加 <button>
按钮 并 增加事件
html
<br>
<button @click="goMyPage2Push3">转到 MyPage2 push 3</button>
在 methods 中增加处理函数, 这里可以使用name , 也可以使用 path
js
goMyPage2Push3(){
this.$router.push({
// name: 'myPage2',
path: '/myPage2/:id/:title',
params: {
id: 123,
title: '标题'
}
})
},
6.5.2.replace
类似于 push
,但它不会向浏览器的历史栈添加新的记录,而是替换当前的记录。
6.5.2.1.测试跳转
在 /views/AboutView.vue
增加 <button>
按钮 并 增加事件
html
<br>
<button @click="goMyPageReplace">转到 MyPage replace</button>
<br>
<button @click="goMyPageReplace2">转到 MyPage replace 2</button>
<br>
<button @click="goMyPage2Replace3">转到 MyPage2 replace 3</button>
在 methods 中增加处理函数, 这里可以使用name , 也可以使用 path
json
goMyPageReplace(){
this.$router.replace('/myPage')
},
goMyPageReplace2(){
this.$router.replace({
path: '/myPage',
query: {
id: 123,
title: '标题'
}
})
},
goMyPage2Replace3(){
this.$router.replace({
// name: 'myPage2',
path: '/myPage2/:id/:title',
params: {
id: 123,
title: '标题'
}
})
}
6.5.3.比较
this.$router.push
和 this.$router.replace
都是 Vue Router 提供的编程式导航方法,用于在单页面应用中进行路由切换。它们的主要区别在于浏览器历史记录和后退操作:
-
this.$router.push()
- 当调用
this.$router.push(path)
或this.$router.push({ path: '...' })
时,会将当前路由添加到浏览器的历史栈中。 - 这意味着用户点击浏览器的"后退"按钮时,他们将返回到之前的页面。
- 当调用
-
this.$router.replace()
- 而当调用
this.$router.replace(path)
或this.$router.replace({ path: '...' })
时,不会向浏览器的历史栈添加新的条目。 - 相反,它会替换当前的路由条目,因此当用户点击"后退"按钮时,他们将直接跳转到上一个(再上一个)页面,而不是回到使用
replace
方法替换掉的那个页面。
- 而当调用
总结来说:
- 如果你希望用户的导航动作可以回溯,就使用
push
。 - 如果你想实现类似于重定向的效果,使得新页面加载后用户不能通过点击后退按钮返回原页面,则使用
replace
。
6.5.4.历史跳转
类似于 BOM中的 history
vue-two/src/views/MyPage.vue
在 /views/MyPage.vue
增加 <button>
按钮 并 增加事件
html
<div>
<button @click="goBackGo">go(-1)</button>
<button @click="goBack">back</button>
<button @click="goForward">forward</button>
<button @click="goForwardGo">go(1)</button>
</div>
在 methods 中增加处理函数, 测试可知与浏览器的前进后退按钮产生相同的效果
json
methods: {
goBack() {
this.$router.back()
},
goForward() {
this.$router.forward()
},
goBackGo() {
this.$router.go(-1)
},
goForwardGo() {
this.$router.go(1)
}
}
6.6.路由缓存及事件
6.6.1.<keep-live>
标签
默认情况下 , 当切换路由后, 原有组件是被销毁的
6.6.1.1.销毁前函数监听
修改 /views/Page1.vue
增加 name组件名 及 销毁前函数
vue
<template>
<div>
<h1>page1</h1>
</div>
</template>
<script >
export default {
name: 'Page1',
beforeDestroy() {
console.log('page1 beforeDestroy')
},
}
</script>
修改 /views/Page2.vue
增加 name组件名 及 销毁前函数
vue
<template>
<div>
<h1>page2 <input type="text"> </h1>
</div>
</template>
<script >
export default {
name: 'Page2',
beforeDestroy() {
console.log('page2 beforeDestroy')
},
}
</script>
在 MyPage.vue 组件中 点击 page1, page2 进行切换时, 发现每一次切换对应的组件都会调用 销毁前函数
6.6.1.2.<keep-live>
标签
修改 在 /views/MyPage.vue
组件, 在 显示标签 <router-view></router-view>
外 增加 <keep-live>
标签
html
<keep-alive >
<router-view></router-view>
</keep-alive>
然后再测试, 就会发现 点击 page1, page2 进行切换时, 不会 再 调用 销毁前函数, 表明page1, page2 两个组件并没有被销毁
6.6.1.3. include , exclude 属性
在 <keep-live>
标签 上可以增加 include , exclude 属性, 分别 来指定哪些组件需要缓存或不需要缓存
属性的值为 各组件的名
多个使用
,
连接
只对 Page1 组件进行缓存
html
<keep-alive include="Page1" >
<router-view></router-view>
</keep-alive>
不对 Page1组件进行缓存
html
<keep-alive exclude="Page1">
<router-view></router-view>
</keep-alive>
6.6.2.缓存路由事件
当一个 不被 销毁的组件, 被激活, 或者失活时, 分别对应两个钩子函数
js
activated() {
// 激活函数
console.log('page1 activated')
},
deactivated() {
// 失活函数
console.log('page1 deactivated')
}
6.7.路由守卫(拦截器)
Vue 2 中提供了多种路由守卫(Route Guards),它们是钩子函数,允许在路由切换的过程中进行拦截,
根据需要决定是否允许导航发生、如何发生以及在导航完成后执行特定的操作。
6.7.1.前置守卫
也叫, 全局前置守卫:在编写在 路由index.js文件中
-
router.beforeEach((to, from, next) => {})
-
这个守卫发生在每次路由即将改变前,参数
to
和from
分别表示目标路由和当前路由对象,而next
是一个函数,调用它才能进行下一步操作。 -
可以使用
next()
来继续导航,next(false)
来取消当前导航,或next('/other/path')
跳转到其他路径。
js
//全局前置路由守卫------------初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
console.log('前置路由守卫',to,from)
if(to.query.id == null ){ //判断条件
console.log('跳转时没有传id')
next()
}else{
next(false)
}
})
判断跳转时, 是否向目标组件以 query形式传递 id , 没有可以继续跳转, 传递了 就不能跳转
6.7.2.全局解析守卫
全局解析守卫:
router.beforeResolve((to, from, next) => {})
- 类似于
beforeEach
,但会在所有异步依赖项完成之后,但在渲染之前被调用,适合处理异步数据获取并基于这些数据决定是否继续导航。
6.7.3.后置守卫
也叫, 全局后置守卫:
router.afterEach((to, from) => {})
- 这个守卫发生在每次路由切换成功之后,不支持中断,主要用于记录路由历史、页面标题设置等操作。
js
//全局后置路由守卫------------初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from)
console.log('跳转成功后 做点什么')
})
6.7.4.独享守卫
也叫 , 路由独享前置守卫: 写在路由配置项中
- 通常在定义路由时,在路由配置的
meta
字段中添加自定义属性,并在路由文件或者全局路由配置的地方使用beforeEnter
守卫:
json
{
path: 'page1',
name: 'Page1',
component: Page1,
meta:{isAuth:false},
beforeEnter: (to, from, next) => {
console.log('独享路由守卫',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
next()
}else{
next(false)
}
}
},
6.7.4.组件内守卫
编写在组件内的钩子函数
6.7.4.1.组件内的路由进入守卫:
- 使用
beforeRouteEnter
生命周期钩子:进入该组件时被调用
先在 路由 index.js 文件中 为 MyPage2组件增加 meta属性
json
{
path: '/myPage2/:id/:title',
name: 'myPage2',
component: MyPage2,
meta:{isAuth:true}
}
再在 MyPage2 组件中增加钩子函数, 进入到当前组件时调用
javascript
//通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
console.log('About--beforeRouteEnter',to,from)
// 不可以直接访问 this,因为此时组件实例还没创建
// 可以通过传入回调函数来访问组件实例
if(to.meta.isAuth){
next(v=>{
console.log("next-route:", v.$route)
})
}else{
next(false)
}
},
6.7.4.2.组件内的路由更新守卫:
- 当路由改变导致组件复用且组件对应的路由参数发生变化时触发:
javascript
beforeRouteUpdate(to, from, next) {
// 在这个钩子中,可以访问组件实例 `this`
// 并可以对响应式数据进行更改
console.log(this.$route)
next();
},
6.7.4.3.组件内的路由离开守卫:
- 在导航离开该组件的对应路由时触发:
javascript
//通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next) {
// 确保在用户离开前保存数据或取消某项操作
const answer = window.confirm('是否想离开?');
if (answer) {
console.log('About--beforeRouteLeave',to,from)
next();
} else {
next(false);
}
},