Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转;
route:首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;
routes:它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合;
router:译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;
Vue路由模式有hash模式,使用URL的hash值来作为路由,支持所有浏览器;history模式,依赖于HTML5 API(旧浏览器不支持)和HTTP服务端配置;abstract模式,适用于所有JavaScript环境。
Vue 路由是指根据 url 分配到对应的处理程序;作用就是解析 URL,调用对应的控制器(的方法,并传递参数)。Vue 路由有助于在浏览器的 URL 或历史记录与 Vue 组件之间建立链接,从而允许某些路径渲染与之关联的任何一个视图。那么 vue 路由模式有哪些呢?
1.hash 模式
使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,其显示的网路路径中会有 “#” 号,有一点点丑。这是最安全的模式,因为他兼容所有的浏览器和服务器。
2.history 模式
美化后的 hash 模式,会去掉路径中的 “#”。依赖于 Html5 的 history,pushState API,所以要担心 IE9 以及一下的版本,感觉不用担心。并且还包括 back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作。
但是 history 也是有缺点的,不怕前进后退跳转,就怕刷新(如果后端没有准备的话),因为刷新是实实在在地去请求服务器了。
3.abstract 路由模式
abstract 是 vue 路由中的第三种模式,本身是用来在不支持浏览器 API 的环境中,充当 fallback,而不论是 hash 还是 history 模式都会对浏览器上的 url 产生作用,本文要实现的功能就是在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由 path,这就利用到了 abstract 这种与浏览器分离的路由模式。
总结:vue 路由模式有 hash 模式,使用 URL 的 hash 值来作为路由,支持所有浏览器;其 url 路径会出现“#”字符;history 模式,依赖于 HTML5 API(旧浏览器不支持)和 HTTP 服务端配置,没有后台配置的话,页面刷新时会出现 404;abstract 模式,适用于所有 JavaScript 环境,如果没有浏览器 API,路由器将自动被强制进入此模式。
在传统的 web 开发中每一个请求地址都会请求服务器来进行处理,但是用户有些操作则无需请求服务器,直接页面端修改下逻辑就能达到目的,在这种方式下最好的方法是使用路由,因为使用路由时,URL 会随着改变,用户浏览一个网页时可以直接复制或收藏当前页面的 URL 给别人,这种方式对于搜索引擎和用户来说都是友好的
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = []
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
routes
})
export default router
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
每个守卫方法接收三个参数:
to: Route: 即将要进入的目标 路由对象
from: Route: 当前导航正要离开的路由
next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: 'home' 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
- 全局前置守卫 beforeEach
你可以使用 router.beforeEach 注册一个全局前置守卫:
const router = new VueRouter({ ... })
router.beforeEach(async(to, from, next) => {
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
next({ path: '/' })
} else {
const hasGetUserInfo = store.getters.name
if (hasGetUserInfo) {
next()
} else {
try {
await store.dispatch('user/getInfo')
next()
} catch (error) {
await store.dispatch('user/resetToken')
next(`/login?redirect=${to.path}`)
}
}
}
} else {
if (whiteList.indexOf(to.path) !== -1) {
next()
} else {
next(`/login?redirect=${to.path}`)
}
}
})
- 全局解析守卫 afterEach
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:
router.afterEach((to, from) => {
// ...
})
- 路由独享的守卫
你可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
- beforeRouteEnter
beforeRouteEnter(to, from, next) {
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
//解决:
next(vm => {
// 通过 `vm` 访问组件实例
})
},
- beforeRouteUpdate
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
- beforeRouteLeave
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
router.addRout(routes)
定义路由的时候可以配置 meta 字段:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
// a meta field
meta: { requiresAuth: true }
}
]
}
]
})
// 一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的
//$route.matched 数组。因此,我们需要遍历 $route.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()
}
})
- 异步组件懒加载webpack
当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
//结合 Vue 的异步组件 和 Webpack 的代码分割功能 ,轻松实现路由组件的懒加载。
//有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。
const router = new VueRouter({
routes: [{ path: '/foo', component: () => import('./Foo.vue')
}]
})
或
component: resolve=>(require(["@/components/HelloWorld"],resolve)) } ] })
//2. 组件懒加载方案三: webpack提供的require.ensure() */
{
path: '/home',
name: 'home',
component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
},
vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 .
但是,这种情况下一个组件生成一个js文件
/* vue异步组件技术 */
{ path: '/home', name: 'home', component: resolve => require(['@/components/home'],resolve) },
//单个路由的过渡
//上面的用法会给所有路由设置一样的过渡效果,如果你想让每个路由组件有各自的过渡效果,可以在各路由组件内使用 并设置不同的 name。
const Foo = {
template: `
...
`
}
const Bar = {
template: `
`
}
//基于路由的动态过渡
//还可以基于当前路由与目标路由的变化关系,动态设置过渡效果:
// 接着在父组件内
// watch $route 决定使用哪种过渡
watch: {
'$route' (to, from) {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
}
路由参数
什么是: 从上一个页面组件跳转到下一个页面组件时,顺便携带参数值到下一个页面组件,继续使用!
params参数类型:
//1.修改路由字典中的路由记录对象:
var routes=[
... ...
{path:"/details/:自定义变量名", component: Details , props:true}
]
// params传参数(类似post) 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 配置path,刷新页面id会保留 -- 不配置path,第一次可请求,刷新页面id会消失
跳转方式:下面使用的是借用name跳也可使用path
//1.push: 追加历史记录,即在前一条的记录上在新加一条浏览记录
//2.replace: 覆盖历史记录,即在添加新记录的同时回收原有记录,替换掉原有记录
// html 取参:$route.params.id -- script取参: this.$route.params.id
this.$router.push({name:'home',params: {id:'1'}})
this.$router.replace({name:'home',params: {id:'1'}})
query参数类型:
// query传参数 (类似get,url后面会显示参数) 路由可不配置
跳转方式:下面使用的是借用name跳也可使用path
//1.push: 追加历史记录,即在前一条的记录上在新加一条浏览记录
//2.replace: 覆盖历史记录,即在添加新记录的同时回收原有记录,替换掉原有记录
// html取参:$route.query.id -- script取参:this.$route.query.id
//
this.$router.push({name:'home',query: {id:'1'}})
//this.$router.push({path:'/home',query: {id:'1'}})
this.$router.replace({name:'home',query: {id:'1'}})
//this.$router.replace({ path:'/home',query: {id:'1'} })
其它路由方法
- go
this. $router.go(1) //前进一步 相当于history.forward()
this. $router.go(-1) //后退一步 相当于history.back()
this. $router.go(10)
- back后退
- forward前进
useRouter 获取到当前router对象的方法
router.addRoute 添加路由(vue2.0)
router.removeRoute(‘login’) 删除指定路由
router.hasRoute 查询是否由指定的路由
router.getRoutes 返回所有注册路由
注意:
传递对象 (object不能过长,不然会报错:Failed to load resource: the server responded with a status of 400 (Bad Request))
query传递对象 (类似get,url后面会显示参数) JSON.stringify(obj) 转一下