在路由规则中, * 匹配任意字符,所以只要在路由中添加一个 *路由,那么以后没有匹配到的url都会被导入到这个视图中,可以用来匹配未找到的地址,即404。
测试如下:
Document
首页
个人中心
var index = Vue.extend({
template:'这是首页
'
})
var profile = Vue.extend({
template:'这是{{$route.params.userid}}个人中心
',
mounted(){
if(this.$route.params.userid != '123'){
this.$router.replace('/404')
}
}
})
var notfound = Vue.extend({
template:'您找的页面已经到火星啦!
'
})
var router = new VueRouter({
routes:[
{path:'/',component:index},
{path:'/profile/:userid',component:profile},
// 匹配未找到的userid
{path:'/404',component:notfound},
// 匹配未定义的地址
{path:'*',component:notfound},
]
})
new Vue({
el:'#app',
data:{
},
router:router
})
显示:
可以匹配两类页面未找到的情况:
注意:
在增加匹配404时必须将 * 放在最后一个路径中,因为前面的都已经匹配过而未匹配到时,说明要访问的链接不在可以访问的链接范围内,此时需要来匹配404,即通配符匹配。
有时候在路由中,主要的部分是相同的,但是下面的具体内容可能是不同的。
比如访问用户的个人中心是/user/111/profile/
,查看用户发的贴子是/user/111/posts/
等,这时候就需要用到嵌套路由。
测试如下:
Vue路由
var index = Vue.extend({
template: '这是首页
',
})
var user = Vue.extend({
template: `
这是个人中心
`,
})
var notice = Vue.extend({
template: `
公告1
公告2
`
})
var comment = Vue.extend({
template: `
评论1
评论2
`
})
var follow = Vue.extend({
template: `
您关注的
关注您的
`
})
var router = new VueRouter({
routes: [{
path: '/',
component: index
},
{
path: '/user/:userid',
component: user,
children:[
// 设置默认显示通知
{path:'',component:notice},
{path:'notice',component:notice},
{path:'comment',component:comment},
{path:'follow',component:follow},
]
},
]
})
new Vue({
el: '#app',
data: {
},
router: router
})
显示:
可以看到:
如果在路由下面再定义路由,需要在children属性中添加,同时需要在该路由对应的模板中构建link和view。
之前我们都是使用,用户点击时页面进行更新,但有时候我们需要在JavaScript中手动修改页面的跳转,这时候就要用到编程式导航。
即有两种导航路由的方式:
声明式
即之前一直用的方式
XXX
编程式
router.push(...)
$router.push跳转的原理:
用router.push
方法导航到不同的URL,这个方法会向history栈添加一个新的记录,当用户点击浏览器后退按钮时,会回到之前的URL;
当点击时,
router.push
方法会在内部调用,也就是说,点击等同于调用
router.push(...)
。
router.push
方法常用的方式有以下几种:
router.push('home')
对象
router.push({ path: 'home' })
命名的路由
router.push({ name: 'user', params: { userId: '123' }})
带查询参数
router.push({ path: 'register', query: { plan: 'private' }})
通过JS指定路由还有一种方式router.replace(location, onComplete?, onAbort?)
,它跟router.push
很像,区别是它不会向history添加新记录,而是替换掉当前的history记录。
router.go(n)
方法的参数是一个整数,意思是在history记录中向前或者后退多少步,类似于window.history.go(n)
。
// 在浏览器记录中前进1步,等同于history.forward()
router.go(1)
// 后退1步记录,等同于history.back()
router.go(-1)
// 前进3步记录
router.go(3)
// 如果参数数值过大、history记录不够用,会前进或后退失败
router.go(-100)
router.go(100)
测试如下:
Vue路由
var post = Vue.extend({
template:'这是列表
'
})
var search = Vue.extend({
template:'这是搜索结果
'
})
var profile = Vue.extend({
template:'这是{{$route.params.userid}}个人中心
'
})
var router = new VueRouter({
routes:[
{path:'/post',component:post},
{path:'/search',component:search},
{path:'/profile/:userid',component:profile,name:'myprofile'},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods:{
toPost:function(){
this.$router.push('/post')
},
toProfile:function(){
// this.$router.push('/profile/123')
this.$router.push({name:'myprofile',params:{userid:123}})
},
search(){
this.$router.push({path:'search',query:{kw:'vue'}})
},
toNext(){
this.$router.go(1)
},
toPrevious(){
this.$router.go(-1)
},
}
})
显示:
说明:
(1)通过push进行路由导航时,传递参数有2种常见形式profile/123
和search?kw=vue
,分别对应一下两种传参方式:
profile/123
型的参数this.$router.push('/profile/123')
通过params传递this.$router.push({name:'myprofile',params:{userid:123}})
,如果使用这种方式,需要在定义路由映射时给该路由命名。
对于search?kw=vue
型的参数:this.$router.push({path:'search',query:{kw:'vue'}})
(2)在router.push()
的参数中提供了path时,params参数会被忽略,但是query不会被忽略;如果想要使用params参数,需要提供路由的name或手写完整的带有参数的path,这与(1)中一致。
例如:router.push({ path: '/user', params: { 123 }})
的参数是无效的,路由指向/user
,而router.push({ name: 'user', params: { 123}})
和router.push({ path: '/user/123' })
的参数是有效的,都指向/user/123
。
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。
可以在创建Router实例的时候,在routes配置中给某个路由设置名称。
要链接到一个命名路由,可以给router-link的to属性传一个对象,例如:
User
这与router.push({ name: 'user', params: { userId: 123 }})
是等效的。
测试:
Vue路由
Home
var home = Vue.extend({
template:'这是首页
'
})
var router = new VueRouter({
routes:[
{path:'/',component:home,name:'index'},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods:{
}
})
显示:
还可以传入参数:
Vue路由
Home
var home = Vue.extend({
template:'这是首页
'
})
var router = new VueRouter({
routes:[
{path:'/user/:userid',component:home,name:'index'},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods:{
}
})
显示:
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有sidebar(侧导航) 和main(主内容) 两个视图,这个时候命名视图就派上用场了。
可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。
如果router-view没有设置名字,那么默认为default。
一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件,并在components中实现name与组件的映射。
进行测试:
Vue路由
var headerc = Vue.extend({
template: '顶部
'
})
var leftc = Vue.extend({
template: '左边
'
})
var rightc = Vue.extend({
template: '右边
'
})
var footerc = Vue.extend({
template: '底部
'
})
var router = new VueRouter({
routes: [{
path: '/',
components: {
header:headerc,
left:leftc,
right:rightc,
footer:footerc
},
name: 'index'
}, ]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods: {}
})
显示:
重定向是通过routes配置的redirect参数来完成的。
测试如下:
Vue路由
var login = Vue.extend({
template:'请登录
'
})
var router = new VueRouter({
routes: [
{path:'/',redirect:'/login'},
{path:'/login',component:login},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods: {}
})
显示:
同时,重定向的目标也可以是一个命名的路由,如下:
Vue路由
var login = Vue.extend({
template:'请登录
'
})
var router = new VueRouter({
routes: [
{path:'/',redirect:{name:'relogin'}},
{path:'/login',component:login,name:'relogin'},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods: {}
})
测试效果与之前相同。
还可以命别名,测试如下:
Vue路由
var login = Vue.extend({
template:'请登录
'
})
var router = new VueRouter({
routes: [
{path:'/',redirect:'/login'},
{path:'/login',component:login,alias:'/signin'},
]
})
new Vue({
el: '#app',
data: {
},
router: router,
methods: {}
})
显示:
别名说明:
/login
的别名是/signin
,意味着,当用户访问/signin
时,URL会保持为/signin
,但是路由匹配则为/login
,就像用户访问/login
一样。
更多关于Vue-Router的内容可参考官方文档https://router.vuejs.org/zh/。