- 单页 Web 应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的导航链接不会刷新页面,只会做页面的局部更新,如后台管理系统。
- 数据需要通过 ajax 请求获取。
vue-router官方提供的一个与vue深度集成的路由插件,适合用于构建SPA(但应用)应用一个路由就是一组映射关系,将路径和组件映射起来,通过路径切换不同的组件,即浏览器路径变化时加载不同的组件
官网地址
vue-router使用
1、安装
npm install vue-router --save
2、创建路由
src下创建一个文件夹router,router下新建index.js文件
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About'
import Home from '../components/Home'
//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
3、注册路由
main.js中使用路由
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入VueRouter
import VueRouter from 'vue-router'
//引入路由器
import router from './router'
//关闭Vue的生产提示
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)
//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router
})
4、使用切换
5、指定展示位置
使用router-view实现位置展示
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- 原始html中我们使用a标签实现页面的跳转 -->
<!-- <a class="list-group-item active" href="./about.html">About</a> -->
<!-- <a class="list-group-item" href="./home.html">Home</a> -->
<!-- Vue中借助router-link标签实现路由的切换 -->
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的呈现位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
备注
1、路由组件通常放在pages文件夹中 一般组件通常放在components文件夹
2、通过切换隐藏了路由组件,默认是被销毁的需要时再去挂载
3、每个组件都已自己的$route属性 里面存储自己的路由信息
4、整个应用只有一个router,可以通过组件的$router属性获取到
路由嵌套
routes: [
{
path: '/index',
component: Index,
children:[//通过children配置路由
{
path:'index2',//此处一定不要写有斜线/
component: Index2,
},
{
path:'index3',
component: Index3,
}
]
}
]
跳转
<router-link to="/index/index2"></router-link>
要展示的地方还是使用<router-view></router-view>展示
路由传参
query参数
1、路由地址配置,路由地址还是在router下的index.js正常配置
2、传递参数(两种方式)
3、接受参数
在目标地址页面组件中设置参数
<template>
<ul>
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
mounted() {
// console.log(this.$route)
},
}
</script>
params参数
1、声明路由接受params参数
routes:[
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title',//使用占位符说明接受params参数
component:Detail,
}
]
}
]
}
]
2、传递参数
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<!-- <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link> -->
<!-- 跳转路由并携带params参数,to的对象写法 这种不能使用path配置 只能用name -->
<router-link :to="{
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>
</li>
</ul>
<hr>
<router-view></router-view>
</div>
3、展示
<template>
<ul>
<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>
</ul>
</template>
<script>
export default {
name:'Detail',
mounted() {
// console.log(this.$route)
},
}
</script>
路由的props参数配置
作用
让路由组件更方便收到参数
第一种写法
值为对象,该对象中的所有key-value都会以props的形式传给detail组件
第二种写法
值为布尔值,若布尔值为真 就会把该路由组件收到的所有params参数以props形式传给detail组件
第三种写法
值为函数
命名路由
给路由起个名字使用name
作用:简化跳转
router-link的replace模式
1、作用:控制路由跳转时操作浏览器历史记录的模式
2、浏览器有push和replace两种写入方式,push时追加历史记录,replace替换当前的记录路由跳转时默认时push
3、改变路由跳转时写入模式为replace 在router-link中使用replace
<router-link replace class="list-group-item" active-class="active" to="/home/news">News</router-link>
编程式路由导航
1、不借助router-link实现的路由方式(router-link最终转成a 有些情况下是button、或者定时路由跳转功能),使用编程式导航路由让路由跳转更加灵活
2、具体使用
$route的两个api
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<button @click="pushShow(m)">push查看</button>
<button @click="replaceShow(m)">replace查看</button>
</li>
</ul>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
name:'Message',
data() {
return {
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'}
]
}
},
methods: {
pushShow(m){
this.$router.push({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
this.$router.replace({
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
},
}
</script>
其他api
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
this.$router.back(): 请求(返回)上一个记录路由
this.$router.go(-1): 请求(返回)上一个记录路由
this.$router.go(1): 请求下一个记录路由
缓存路由组件
让不展示的路由保持挂载不被销毁(需求场景:用户输入内容后 中途有跳转其他路由,重新返回后之前输入的内容不见了)
实现,在要展示组件的router-view处使用<keep-alive></keep-alive>包裹,使用include说明要缓存哪个组件,写的话router-view处展示的组件都缓存,include值是对应的是组件的名字,不是路由的name
<keep-alive include="detail">
<router-view></router-view>
</keep-alive>
使用数组缓存多个组件
<keep-alive :include="['news','detail']">
<router-view></router-view>
</keep-alive>
vue两个新的生命钩子
路由组件独有的两个钩子,用于捕获组件的激活状态
activated() {
console.log("demo组件被激活")
},
deactivated() {
console.log("demo组件失活")
}
路由守卫
全局前置路由守卫、全局后置路由守卫
//创建路由器 但是没暴露
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
name:'zhuye',
path:'/home',
component:Home,
meta:{title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
//路由原信息 可以自定义属性
meta:{isAuth:true,title:'新闻'}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
children:[
{
name:'xiangqing',
path:'detail',
component:Detail,
meta:{isAuth:true,title:'详情'},
}
]
}
]
}
]
})
//全局前置路由守卫————初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next)=>{
console.log('前置路由守卫',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='demo'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
})
//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from)
document.title = to.meta.title || '测试'
})
export default router
独享路由守卫
只对指定路由单独配置守卫
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{title:'关于'}
},
{
name:'zhuye',
path:'/home',
component:Home,
meta:{title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'},
beforeEnter: (to, from, next) => {
console.log('独享路由守卫',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
}
}
]
}
]
})
//全局后置路由守卫可以和单独守卫配合使用
router.afterEach((to,from)=>{
console.log('后置路由守卫',to,from)
document.title = to.meta.title || 'dmp'
})
export default router
组件内路由守卫
在组件内使用
<template>
<h2>我是About的内容</h2>
</template>
<script>
export default {
name:'About',
//通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {
console.log('About--beforeRouteEnter',to,from)
if(to.meta.isAuth){ //判断是否需要鉴权
if(localStorage.getItem('school')==='dmp'){
next()
}else{
alert('学校名不对,无权限查看!')
}
}else{
next()
}
},
//通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {
console.log('About--beforeRouteLeave',to,from)
next()
}
}
</script>
路由模式
1、两种模式
hash模式:路由默认的工作模式,即路径#后面的部分不会作为参数发送给服务器localhost/#/index
history模式:路径没有#
2、如何配置模式
export default new Router({
//这里配置路由方式,默认hash
mode:'history',
routes: [
{
path: '/index',
component: Index
}
]
})
3、如何解决history下的404问题
后端配置
不同的服务端有不同的解决方式。参考地址:文本地址
前端配置
基于 Node.js 的 Express
对于 Node.js/Express,请考虑使用 connect-history-api-fallback 中间件