Vue路由管理之vue-router
Vue路由管理之vue-router
1.动态路由匹配
我们经常需要把某种模式匹配到的所有路由,全部映射到同一个组件。我们可以在vue-router的路由路径中使用“动态路由参数”来达到这个效果。
一个“路径参数”使用冒号标记。当匹配到一个路由时,参数值会被设置到this.$route.params,可以在每个组件内使用。
复用组件时,组件的生命周期钩子不会再被调用。如果要对路由参数的变化做出响应,可以watch(监测变化)$route对象。或者引入beforeRouteUpdate导航守卫
高级匹配模式 path-to-regexp
匹配优先级
匹配的优先级按照路由的定义顺序:谁先定义的,谁的优先级就高。
2.嵌套路由
使用children参数配置
3.编程式导航
// 字符串 router.push('home') // 对象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: 123 }}) // 带查询参数,变成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了path,params会被忽略。
同样的规则也适用于router-link组件的to属性。
router.replace和router.push很像,唯一的不同就是,它不会向history添加新记录,而是跟它的方法名一样——替换当前的history记录。
声明式 编程式 <router-link :to="..."> router.push(...) 声明式 编程式 <router-link :to="..." replace> router.replace(...) router.go(n) // 在浏览器记录中前进一步,等同于 history.forward() router.go(1) // 后退一步记录,等同于 history.back() router.go(-1) // 前进 3 步记录 router.go(3) // 如果 history 记录不够用,那就默默地失败呗 router.go(-100) router.go(100)
命名视图
<router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view> const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] })
重定向和别名
const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] }) const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
别名的功能可以自由地将UI结构映射到任意的URL,而不是受限于配置的嵌套路由结构。
路由组件参数
取代与 $route 的耦合
const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] }) const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true }, // 对于包含命名视图的路由,你必须分别为每个命名视图添加 `props` 选项: { path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] }) const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] })
HTML5 HISTORY模式
vue-router默认hash模式——使用URL的hash来模拟一个完整的URL,于是当URL改变时,页面不会重新加载。
const router = new VueRouter({ mode: 'history', routes: [...] }) history模式需要后台配置支持。 nginx location / { try_files $uri $uri/ /index.html; } Apache <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] </IfModule>
导航守卫
vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。
记住参数或查询的改变并不会触发进入/离开的导航守卫。可以通过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫。
全局守卫
router,beforeEach((to,from.next)=>{
})
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步执行,此时导航在所有守卫resolve完之前一直处于等待中。
确保要调用next方法,否则钩子就不会被resolved。
全局解析守卫
router.beforeResolve
全局后置钩子(不接受next函数也不会改变导航本身)
router.afterEach((to, from) => {
// ...
})
路由独享的守卫
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
组件内的守卫
beforeRouteEnter(不能访问this,但可以通过传一个回调给next来访问组件实例)
beforeRouteUpdate(this已可用,不支持传递回调)
beforeRouteLeave(this已可用,不支持传递回调,离开守卫通常用来禁止用户在还未保存修改前突然离开,该导航可以通过next(false)来取消)
完整的导航解析流程
1.导航被触发
2.在失活的组件里调用离开守卫
3.调用全局的beforeEach守卫
4.在重用的组件里调用beforeRouteUpdate守卫
5.在路由配置里调用beforeEnter
6.解析异步路由组件
7.在被激活的组件里调用beforeRouteEnter
8.调用全局的beforeResolve
9.导航被确认
10.调用全局的afterEach钩子
11.触发DOM更新
12.用创建好的实例调用beforeRouteEnter守卫中传给next的回调函数
路由元信息
定义路由的时候可以配置meta字段($route.matched)
路由懒加载
定义一个能够被webpack自动代码分隔的异步组件
const Foo = () => import('./Foo.vue') const router = new VueRouter({ routes: [ { path: '/foo', component: Foo } ] })
滚动行为
const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 期望滚动到哪个的位置 } })
第三个参数savedPosition当且仅当popstate导航时才可用。
如果返回一个falsy的值,或者是一个空对象,那么不会发生滚动。