vue前端路由
路由
对应关系
:地址和页面上组件的关系 (Hash地址和组件的关系)SPA
单页面应用
拿到当前路由的完整地址
location.href
输出:‘http://127.0.0.1:5500/src/test/%E9%94%9A%E9%93%BE%E6%8E%A5.html#b41’
拿到当前路由的hash地址location.hash
‘#b11’
前端路由工作方式
- 用户
点击页面上的路由链接
- 导致了
URL地址栏中的hash值
发生了变化 - 前端路由
监听
到了hash地址的变化 - 前端路由把
当前地址对应的组件
渲染到浏览器中
手写简单的路由
- App.vue根组件使用动态组件
- 本质就是点击某个连接改变
hash地址
的值 - 通过created里面的
window.onhashchange
来监听hash地址的改变通过location.hash
来获取新的hash地址
<template>
<div>
<h1>App根组件aa</h1>
<div>
<a href="#/home" @click="change('Home')">首页</a>
<a href="#/movie" @click="change('Movie')">电影</a>
<a href="#/about" @click="change('About')">关于</a>
</div>
<div>
<component :is="choose"></component>
</div>
</div>
</template>
<script>
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'
export default {
components: {
Home,
Movie,
About
},
created () {
window.onhashchange = () => {
console.log('监听到hash地址的变化', location.hash)
}
},
data () {
return {
choose: 'Home'
}
},
methods: {
change (val) {
this.choose = val
console.log(val)
}
}
}
</script>
<style lang="less" scoped>
</style>
vue-router
如何使用vue-router
- vue-router 是官方给出的路由解决方案,它只能结合vue项目进行使用,能轻松管理SPA项目中组件的切换
安装vue-router包
创建路由模块
导入并挂载路由模块
声明路由链接
和占位符
npm i vue-router@3.5.5 -S
/src/router/index.js
创建路由模块
// 导入 Vue和vue-router的包
import Vue from 'vue'
import VueRouter from 'vue-router'
// 调用vue.use函数把 VueRouter 安装为Vue的插件
Vue.use(VueRouter)
// 创建路由的实例对象
const router = new VueRouter()
// 向外共享路由的实例对象
export default router
-
main.js 挂载路由
-
在路由模块下面注册路由规则
// 导入 Vue和vue-router的包
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home.vue'
import Movie from '@/components/Movie.vue'
import About from '@/components/About.vue'
// 调用vue.use函数把 VueRouter 安装为Vue的插件
Vue.use(VueRouter)
// 创建路由的实例对象
const router = new VueRouter({
// 定义hash地址和组件之间的对应关系的
routes: [
// 路由规则
{
path: '/home',
component: Home
},
{
path: '/movie',
component: Movie
},
{
path: '/about',
component: About
}
]
})
// 向外共享路由的实例对象
export default router
- App2.vue使用
- 使用
router-view
来进行组件的占位符
- 连接标签使用
router-link
来跳转
<template>
<div>
<h1>App2根组件</h1>
<div>
<router-link to="/home">首页</router-link>
<router-link to="/movie">电影</router-link>
<router-link to="/about">关于</router-link>
</div>
<!-- 只要导入了路由模块可以使用router-view组件了 -->
<!-- 组件的作用就是占位符 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'DemoApp2',
}
</script>
<style lang="less" scoped>
.box{
display: flex;
}
</style>
路由重定向
- 用户在访问地址A的时候,
强制用户
跳转到地址C,从而展示特定的组件页面。通过路由规则的redirect
属性,指定一个新的路由地址,可以很方便的设置路由的重定向
// 创建路由的实例对象
const router = new VueRouter({
// 定义hash地址和组件之间的对应关系的
routes: [
// 路由规则
// 重定向
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home
},
{
path: '/movie',
component: Movie
},
{
path: '/about',
component: About
}
]
})
嵌套路由
- 子组件内嵌套使用
<template>
<div class="box1">
<h1>About组件</h1>
<!-- 子级路由链接 -->
<router-link to="/about/tab1">tab1</router-link>
<router-link to="/about/tab2">tab2</router-link>
<hr/>
<!-- 子级路由占位符 -->
<router-view></router-view>
</div>
</template>
通过children属性声明子路由规则
- 在src/router/index.js路由模块中,导入需要的组件,并使用
children属性
声明子路由规则 默认子路由
和路由重定向
都可以实现点击之后优先展示哪个组件
// 创建路由的实例对象
const router = new VueRouter({
// 定义hash地址和组件之间的对应关系的
routes: [
// 子路由规则
// 默认子路由,如果children数组中,某个路由规则的path值为空字符串,则这条路由规则叫做默认子路由
{
path: '/about',
component: About,
// redirect: '/about/tab1',
children: [
{ path: '', component: Tab1 }, // 默认子路由功能和路由重定向一致
{ path: 'tab1', component: Tab1 },
{ path: 'tab2', component: Tab2 }
]
}
]
})
动态路由匹配
静态路由的缺点
复用性差
思考一下,如果要写一万条,我们要写一万条路由导向吗?
<div>
<router-link to="/movie/1">电影1</router-link>
<router-link to="/movie/2">电影2</router-link>
<router-link to="/movie/3">电影3</router-link>
</div>
{ path: '/movie/1', component: Movie }
{ path: '/movie/2', component: Movie }
{ path: '/movie/3', component: Movie }
动态参数项
- 把hash地址中
可变的部分
定义为参数项
,从而提高路由规则的复用性 - 在vue-router中使用
英文的冒号:
来定义路由的参数项
{ path: '/movie/:id', component: Movie }
// 在movie组件内希望拿到id来展示对应的值
{
path: '/movie/:id',
component: Movie
},
this对象拿到参数
<template>
<div class="box3">
<h1>Movie组件</h1>
<h3>这是组件传递的值------{{this.$route.params.id}}</h3>
<button @click="showThis">打印this</button>
</div>
</template>
为路由规则开始props传参
- 开启props传参
// 在movie组件内希望拿到id来展示对应的值
{
path: '/movie/:id',
component: Movie,
props: true
},
- 组件内props接收参数
<template>
<div class="box3">
<h1>Movie组件</h1>
<h3>这是组件传递的值------{{id}}</h3>
</div>
</template>
<script>
export default {
name: 'Demo3Movie',
// 接收props参数
props: ['id'],
</script>
query和fullPath
- 在hash地址中,
/
后面的参数项,叫做路径参数
- 在路由参数对象中,需要使用
this.$router.params
来访问路径参数 - 在hash地址中,
?
后面的参数项,叫做查询参数
- 在路由参数对象中,需要使用
this.$router.query
来访问路径参数 - 在路由参数对象中,需要使用
this.$router.fullPath
来访问完整路由地址
<router-link to="/movie/1">电影1</router-link>
<router-link to="/movie/1?name='zs'&age=20">电影1</router-link>
声明式导航&编程式导航
- 在浏览器中,
点击连接
实现导航的方式,叫做声明式导航
。 - 在浏览器中,
调用API方式
实现导航的方式,叫做编程式导航
。
编程式导航
this.$router.push('hash’地址)
- 跳转到指定的hash地址,并
增加一条历史记录
this.$router.replace('hash’地址)
- 跳转到指定的hash地址,
直接替换掉当前的页面
this.$router.go(数值 n)
- 调用此方法可以在浏览器的历史记录里面
前进或者后退
后退层数超出最大层数则不跳转
this.$router.go(-1) // 后退到之前的页面
this.$router.go(1) // 前进到之前的页面
- 前进和后退一层时的简化写法
this.$router.back() // 后退一层
this.$router.forward() // 前进一层
导航守卫
- 可以控制路由的访问权限
全局前置守卫
- 在跳转之前就会触发守卫(类似于请求拦截器),在全局前置守卫中,程序员可以对每个路由进行
访问权限
的控制
const router = new VueRouter({
})
// 为router声明前置导航
// to 表示将要访问的路由信息对象
// from 是将要离开的路由对象信息
// next 是一个函数,调用next() 表示放行,允许这次路由导航
router.beforeEach(function (to, from, next) {
console.log('要去的路由地址', to)
console.log('离开的路由地址', from)
// 表示放行
/**
* 当用户拥有权限时直接放行 next()
* 用户没有权限时,强制其跳转到登陆页面 next('/login')
* 用户没有权限时,不允许跳转到后台主页 next(false)
*/
next()
})
访问拦截
router.beforeEach(function (to, from, next) {
console.log('要去的路由地址', to)
console.log('离开的路由地址', from)
if (to.path === '/main') {
const token = localStorage.getItem('token')
if (token) {
next() // 访问后台有token,直接放行
} else {
next('/login') // 访问后台没有token,则跳转到login页面
}
} else {
next() // 访问不是后台主页,直接放行
}
})