Vue-Router路由治理
- 根底应用
- 进阶
1 根底
- 装置与根本应用
- 动静路由
- 嵌套路由
- 编程式导航
- 命名路由
- 命名视图
- 重定向和别名
- 路由组件传参
- History模式
- Modules
1.1 装置与根本应用
//装置
npm install vue-router --save
//main.js内引入
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//此时在vue实例上会多出`$route`和`$router`两个属性
创立两个页面
//About.vue
<template>
<div>对于页面</div>
</template>
//Detail.vue
<template>
<div>对于页面</div>
</template>
配置路由
//router.js文件
import VueRouter from "vue-router";
import About from './pages/About'
import Detail from './pages/Detail'
export const router = new VueRouter({
routes: [
{
path: '/about',
component: About,
},
{
path: '/detail',
component: Detail
}
]
})
- 引入VueRouter并实例化,引入组件
- 配置对象的
routes
选项,以数组-对象
模式注册路由,包含门路与组件
在mian.js中引入router实例并注册
//mian.js
import { router } from './router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
//此时能够察看到$router与$route的相干配置
在App.vue中应用路由
<template>
<div id="app">
<router-link to="/about">跳转about</router-link><br />
<router-link to="/detail">跳转detail</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
};
</script>
router-link
为路由入口
,在to中配置门路router-view
为路由进口
,跳转的页面在此处显示
相似于动静组件
,实现了根本的跳转性能,路由的性能更加弱小
$router相似于$store,在根实例注册后,子组件都能够拜访到原路由实例,不须要频繁的在子组件中引入。$route是以后路由
1.2 动静路由
依据不同的门路参数跳转至同一组件,显示不同的数据
//router.js
{
path: '/about:id',
component: About,
},
//App.vue
<template>
<div id="app">
<router-link to="/about/:'1'">用户1</router-link><br />
<button @click="to">用户2</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: "App",
methods: {
to() {
this.$router.push('/about/:"2"');
},
},
};
</script>
//About.vue
<template>
<div>对于页面{{ userId }}</div>
</template>
<script>
export default {
computed: {
userId() {
return this.$route.params.id;
},
},
};
</script>
- 在router中注册的门路增加
:param
- 跳转时能够应用router-link或者应用$router.push,门路中携带参数
-
在跳转至的路由能够通过$route.params拜访动静门路的参数
能够依据参数去申请数据再渲染页面
:
,对应定义的是params参数-
? = &
,能够定义query参数,通过$route.query拜访<router-link to="/about/?id=1">用户1</router-link><br />
通配符
捕捉所有路由或404 Not found路由
{ //匹配所有门路
path:'*'
}
{ //匹配以'/user'结尾的任意门路
path:'/user-*'
}
应用通配符路由时,$route.params会增加一个名为pathMatch参数。蕴含URL通配符匹配的局部
//router.js
{
path: '*',
component: () => import('./pages/Notfound')
}
当跳转的门路匹配失败时,能够匹配通配符门路,并通过
pathMatch
参数提醒谬误的门路
应用’/user-*’,能够设置特定门路下某种页面未找到的提示信息
1.3 嵌套路由
有时在路由跳转后可能还须要路由跳转,这时就须要嵌套多级路由
在路由注册时增加children
属性
//router.js
{
path: '/about',
component: About,
children: [
{
path: 'child',
component: () => import('./pages/Child')
}
]
},
//跳转
<router-link to="/about/child">二级跳转</router-link>
子路由的门路前不须要
/
,不然会认为从跟门路开始
1.4 编程式导航
除了应用router-link申明式
创立a标签的形式进行跳转,也能够是借助router的实例办法编程式
实现跳转
push:向history栈增加
一个新的记录,能够点击浏览器的后退至之前的URL
replace:替换
以后的history栈顶记录
go(n):后退或后退|n|步,正数为后退,负数为后退,记录不够用则失败
this.$router.push({
path: "/detail",
// params: { userId: 123 },
query: { user: "张三" },
});
push中的数据能够应用对象模式,params参数不能与path同时应用,router-link中的
to
也反对对象模式的写法
能够应用name
属性传递params参数
params
参数:必须在门路上增加参数名,并且跳转时应用name属性-
query
参数:不用在注册时在门路上增加信息,跳转时应用path或name都可当在门路中增加了参数,然而跳转时没有传递params参数,也会跳转失败
应用name属性时,反对同时传递params与query参数
1.5 命名路由
上述曾经对name进行了一些介绍,是对路由的命名
能够简化门路过长的问题,同时防止params参数的问题
routes: [
{
path: '/user/:userId',
name: 'user',
component: User
}
]
1.6 命名视图
router-view中能够增加name
属性,对应路由中的组件
注册路由时的components能够是对象模式,蕴含多个组件,key提供给name抉择
//router.js
{
name: 'detail',
path: '/detail/:userId',
components: {
default: Detail,
a: () => import('./pages/Ads')
}
},
//视图
<router-view></router-view>
<router-view name="a"></router-view>
没有name属性的视图,应用
default
的组件
1.7 重定向和别名
重定向
拜访’/a’重定向’/b’,URL与匹配的路由都换成’/b’
//门路
routes: [
{ path: '/a', redirect: '/b' }
]
//命名
routes: [
{ path: '/a', redirect: { name: 'foo' }}
]
//动静办法
routes: [
{ path: '/a', redirect: to => {
// 办法接管 指标路由 作为参数
// return 重定向的 字符串门路/门路对象
}}
]
能够在返回主页时将根门路重定向为子路由门路,保障页面的填充
别名
‘/a’的别名’b’,当拜访’/b’时,URL依然是’/b’,然而路由匹配为’/a’,相当于拜访’/a’,只是名字不同
routes: [
{ path: '/a', component: A, alias: '/b' }
]
能够自在地将UI构造映射到任意的URL,不受限与配置的嵌套的路由构造
1.8 路由组件传参
props
属性:boolean|Object|Function
$route会使组件与对应路由高耦合,导致组件只能在特定的URL上应用,限度灵活性。
应用props属性能够将组件和路由解耦
//对象模式
{
name:'detail',
path:'/detail',
component:Detail,
props:{foo:'a',bar:'b'}
}
在Detail组件中,能够间接在props中申明后应用
对象模式传递的是静态数据,在配置的时候就写好的,应用场景较少
//布尔模式
{
...
props:true,
}
//多组件
{
...
components:{Detial,Ads},
props:{Detail:true,Ads:false}
}
将路由跳转时的
params
参数传入组件中,在组件的props中申明后应用
//函数模式
{
...
props($route){
return {
id:$route.params.userId,
name:$route.query.user
}
}
}
//解构赋值简写 - 相似于vuex的action中的context对象
{
...
props({params,query}){
return {
id:params.userId,
name:query.user
}
}
}
在不应用props的状况下,传递的参数全副都在URL上,须要应用计算属性一一获取
应用props的函数模式,能够将params和query参数以及静态数据在组件中的props中申明
这样简化了取值的操作,解耦合
1.9 History模式
router中的配置除了routes
选项外,还要其余选项,例如mode
mode默认为hash,地址栏会有一个#
号,URL扭转时,页面不会从新加载
更改为失常的网址模式,应用mode:'history'
history模式须要肯定的后盾反对
,不然会呈现404
这是因为hash模式下#后的地址作为路由跳转,不会发动http申请,然而在history模式下,刷新页面时,会发动http申请,因为没有#的分隔会将整个地址都作为申请地址
nginx
location / {
try_files $uri $uri/ /index.html;
}
Node.js
const http = require('http')
const fs = require('fs')
cosnt httpPort = 80
http.createServer((req,res)=>{
fs.readFile('index.html','utf-8',(err,content)=>{
if(err){
...
}
res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'})
res.end(content)
})
}).listen(httpPort,()=>{
console.log('Server listening on:http://loaclhost:%s',httpPort)
})
能够在Node.js中应用
connect-history-api-fallback
插件,疾速解决history模式后端地址和前端路由地址的抵触,造成申请失败
2.10 Modules
当嵌套路由的层级过多时,能够将其宰割成多个模块
与vuex拆分的形式相似,不必创立module数组,引入后间接在routes数组中注册即可
//routers文件夹中的index.js 入口文件
import VueRouter from 'vue-router'
import { about } from './modules/about'
import { detail } from './modules/detail'
import { Notfound } from './Notfound'
export const router = new VueRouter({
routes: [
{ path: '/' },
about,
detail,
Notfound
]
})
批改为模块化后须要从新在main.js中引入并注册
2 进阶
- 路由守卫
- 路由元信息
- 过渡动效
- 数据获取
- 滚动行为
- 路由懒加载
- 导航故障
2.1 路由守卫
- 全局前置守卫
- 全局解析守卫
- 全局后置钩子
- 路由独享守卫
- 组件内的守卫
- 整体流程
2.1.1 全局前置守卫
beforeEach
const router = new VueRouter({})
router.beforeEach((to,from,next)=>{})
- to : 指标路由
- from : 来到的路由
-
next : 放行函数,
无参数
间接跳转至指标路由- next(false) 中断以后导航
- next(‘/’)或next({path:’/’}) 指定路由跳转,能够应用
name
以及其余选项 - next(error) 中断以后导航,并将Error实例传入router.onError()执行回调
- next函数仅能被调用一次
//index.js - 模仿未登录用户拜访页面,重定向至登录页面
router.beforeEach((to, from, next) => {
if (to.name !== 'login' && to.name !== 'register' && !isAuthenticated) {
next({ name: 'login' })
} else {
next()
}
})
如果跳转应用的push的形式,被守卫拦挡重定向后会报错,但不影响应用
能够在push后应用catch捕捉谬误
2.1.2 全局解析守卫
beforeResolve
相似于beforeEach
区别:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫被调用
2.1.3 全局后置钩子
afterEach
与守卫不同的是没有next放行函数
router.afterEach((to, from) => {
// ...
})
2.1.4 路由独享守卫
beforeEnter
与全局不同的在于它作为一个路由的配置项,独自管制一个路由
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
to : 跳转至以后路由
from : 由某路由跳转来
能够限度from能够从何处跳转至该路由
2.1.5 组件内的守卫
在组件中作为配置选项
beforeRouteEnter:相似于独享守卫,在组件实例创立前调用,故不能获取vm实例
能够在next中增加回调函数拜访组件实例
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 拜访组件实例
})
}
beforeRouteUpdate:门路扭转,组件被复用时调用,能够拜访vm实例
此时的this代表的时from的路由组件实例
beforeRouteLeave:来到该组件的对应路由时调用,能够拜访该组件vm实例
能够在来到前对组件中的内容进行判断,确认是否来到
2.1.6 整体流程
2.2 路由元信息
meta配置项,存储路由元信息
在间断的路由嵌套中,每一层的路由信息都会被收集到$route.matched数组
中
能够应用数组的遍历办法遍历matched数组对meta字段进行查看
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 确保肯定要调用 next()
}
})
2.3 过渡动效
router-view是根本的动静组件,相当于component标签
所以能够应用transition标签对其进行包裹实现过渡
成果
同样的应用keep-alive实现组件缓存
transition与keep-alive
2.4 数据获取
在路由跳转时常常会随同着从服务器获取数据
导航实现后申请:实现导航后,在组件的申明周期钩子中申请数据。申请实现期间显示”加载”提醒。
应用v-if条件渲染加载页面、谬误页面以及申请胜利页面
在created钩子中申请数据
导航实现前申请:在路由守卫中获取数据,获取胜利后执行导航
beforeRouteEnter中申请数据,在next()
回调
中配置申请取得的数据
2.5 滚动行为
scrollBehavior配置选项
切换至新路由时,页面滚动到顶部或者放弃原先的滚动地位
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 冀望滚动到哪个的地位
}
})
默认状况下不产生滚动,返回svaedPosition时后退/后退与浏览器原生操作统一
return {
x:0,y:0
}
依据坐标间接滚动
meta:{x:0,y:0}
return {
selector:to.meta,
behavior:'smooth'
}
依据元信息进行
平滑滚动
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ x: 0, y: 0 })
}, 500)
})
能够返回一个Promise,resolve中传入滚动信息,实现
异步滚动
2.6 路由懒加载
异步组件
//异步组件工厂函数
const AsyncComponent = (url) => ({
// 须要加载的组件 (应该是一个 `Promise` 对象)
component: import(url),
// 异步组件加载时应用的组件
loading: LoadingComponent,
// 加载失败时应用的组件
error: ErrorComponent,
// 展现加载时组件的延时工夫。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时工夫且组件加载也超时了,
// 则应用加载失败时应用的组件。默认值是:`Infinity`
timeout: 3000
})
应用import()函数异步引入组件,能够在首次渲染时先不下载局部组件
在拜访异步组件时再进行下载
2.7 导航故障
在路由导航失败时能够在push后链式处理错误信息
- isNavigationFailure(failure,NavigationFailureType)
-
NavigationFailureType
- redirected:调用了 next(newLocation) 重定向到了其余中央
- aborted:调用了 next(false) 中断了本次导航
- cancelled:以后导航还没有实现之前又有了一个新的导航
- duplicated:导航被阻止,因为咱们曾经在指标地位了
import VueRouter from 'vue-router'
const { isNavigationFailure, NavigationFailureType } = VueRouter
// 正在尝试拜访 admin 页面
router.push('/admin').catch(failure => {
if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
// 向用户显示一个小告诉
showToast('Login in order to access the admin panel')
}
})
// 正在尝试拜访 admin 页面
router.push('/admin').catch(failure => {
if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
failure.to.path // '/admin'
failure.from.path // '/'
}
})
发表回复