Vue-router
1.基本使用
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app"> <h1>Hello App!</h1> <p> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <router-view></router-view> </div>
|
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' }
const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ]
const router = new VueRouter({ routes })
const app = new Vue({ router }).$mount('#app')
|
2.动态路由匹配
2.1使用动态路径参数
1 2 3 4 5 6 7 8 9 10
| const User = { template: '<div>User</div>' }
const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
|
当匹配到参数时,参数值将被设置到this.$route.params
1 2 3
| const User = { template: '<div>User {{ $route.params.id }}</div>' }
|
多段路径匹配
模式 |
匹配路径 |
$route.params |
/user/:username |
/user/evan |
{username:'evan'} |
/user/:username/post/:post_id |
/user/evan/post/123 |
{username: 'evan', post_id: '123'} |
复用组件(生命周期钩子不会被调用)
简单watch $route
对象:
1 2 3 4 5 6 7 8
| const User = { template: '...', watch: { '$route' (to, from) { } } }
|
导航守卫
1 2 3 4 5 6 7
| const User = { template: '...', beforeRouteUpdate (to, from, next) { } }
|
2.2通配符捕获路由
匹配任意路径
1 2 3 4 5 6 7 8
| { path: '*' } { path: '/user-*' }
|
通配符匹配的参数,会被赋值到pathMatch
1 2 3 4 5 6
| this.$router.push('/user-admin') this.$route.params.pathMatch
this.$router.push('/non-existing') this.$route.params.pathMatch
|
2.3高级路由匹配
使用path-to-regexp
2.4匹配优先级
先匹配到优先级最高
3.嵌套路由
实际场景
1 2 3 4 5 6 7 8
| /user/foo/profile /user/foo/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+
|
示例
1 2 3 4 5 6 7 8
| const User = { template: ` <div class="user"> <h2>User {{ $route.params.id }}</h2> <router-view></router-view> </div> ` }
|
在嵌套的出口渲染组件,需要使用children
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [ { path: 'profile', component: UserProfile }, { path: 'posts', component: UserPosts } ] } ] })
|
提供空的子路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [ { path: '', component: UserHome },
] } ] })
|
4.编程式导航
router.push(location, onComplete?, onAbort?)
点击<router-link :to="...">
等同于router.push(...)
声明式 |
编程式 |
<router-link :to="..."> |
router.push(...) |
参数选择
1 2 3 4 5 6 7 8 9 10 11
| router.push('home')
router.push({ path: 'home' })
router.push({ name: 'user', params: { userId: '123' }})
router.push({ path: 'register', query: { plan: 'private' }})
|
注意点:提供了path
,params
的内容会被忽略
1 2 3 4 5
| const userId = '123' router.push({ name: 'user', params: { userId }}) router.push({ path: `/user/${userId}` })
router.push({ path: '/user', params: { userId }})
|
router.replace(location, onComplete?, onAbort?)
该方法不向history
添加新记录,而是替换当前记录
声明式 |
编程式 |
<router-link :to="..." replace> |
router.replace(...) |
router.go(n)
在history
记录中向前或者后退多少步,类似于window.history.go(n)
5.命名路由
使用name
1 2 3 4 5 6 7 8 9
| const router = new VueRouter({ routes: [ { path: '/user/:userId', name: 'user', component: User } ] })
|
链接到命名路由
1
| <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
|
等同于router.push()
1
| router.push({ name: 'user', params: { userId: 123 }})
|
6.命名视图
使用场景:同级渲染多个视图,如:
1 2 3
| <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>
|
多个视图配置多个组件
1 2 3 4 5 6 7 8 9 10 11 12
| const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] })
|
7.重定向和别名
重定向
普通重定向
1 2 3 4 5
| const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] })
|
命名路由的重定向
1 2 3 4 5
| const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] })
|
带方法的动态重定向
1 2 3 4 5 6 7 8
| const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { }} ] })
|
别名
/a
的别名是/b
,意味着当用户访问/b
时,URL保持为/b
,但是路由依然匹配/a
1 2 3 4 5
| const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
|
8.路由组件传参
在组件中使用$route
会使之与其对应的路由形成高度耦合,从而使组件只能在某些特定URL上使用,限制了灵活性
通过props
解耦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true },
{ path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] })
|
布尔模式
如果props
设置为true
,route.params
将会被设置为组件属性
对象模式
如果props
是一个对象,它会被按照原样设置为组件属性,当props
是静态的时候有用
函数模式
可以通过创建一个函数返回props,这样可以将参数转换成为另一种类型,将静态值与基于路由的值相结合等等
1 2 3 4 5
| const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] })
|
9.HTML5 History 模式
vue-router
默认采用hash模式,使用URL的hash来模拟一个完整的URL
另一种路由的history模式,充分利用history.pushState
来完成URL跳转无需重新加载页面
1 2 3 4
| const router = new VueRouter({ mode: 'history', routes: [...] })
|
此模式需要后端支持,URL无任何匹配时返回index.html