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.jsimport { 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 = 80http.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 // '/' }})