你不知道的vue-router?

1.动态路由匹配

(1)在一个组件中需要不同的用户来渲染这个组件,例如我们有个usercenter,需要根据不同id来渲染
usercenter,这样我们就可以使用动态路由来匹配

const = new Router({
            routes:[
                {
                    path: '/usercenter/:uid',
                    component: usercenter
                }
            ]
        })

路由参数一般通过 :来定义它,但路由匹配成功时,参数会被设置到 this.$route.params,
这样我们就可以在组件中使用了

   const userCenter = {
        template: '<div>{{$route.params.uid}}</div>',
    }

这里我们有两个动态参数 /usercenter/0 导航到 /usercenter/1,
原来的组件就会被复用,但是不会触发钩子函数。
重新创建也可,但复用明显更高效。这里官方提供两个参考:

     //其一:
    //每次改变路由$route对象就会更新相应参数
    const userCenter = {
        template: '...',
        watch:{
            $route(to,from) {
                //在这里执行响应路由变化的操作
            }
        }
    }
//其二:
//通过组件间的导航守卫
cosnt = userCenter = {
    template: '...',
    beforeRouteUpdate(to,from,next) {
        //在这里执行响应路由变化的操作
    }
}

捕获所有 404 not Found

如果想匹配任意路径 ,这里用* 通配符来匹配,这里要注意的是匹配顺序。

  {
        path: '*'
    },
    {
        path: '/usercenter-*'
    }
 当使用通配符时,$route.params会自动添加一个pathMatch的参数。它会包含通配符匹配的部分。
	//给一个{path: '*' ...}
    this.$router.push('/notfound')
    this.$route.params.pathMatch    // notfound
    //给一个{path: '/usercenter-*'}
    this.$router.push('/usercenter-admin')
    this.$route.params.pathMatch    // admin
    所有路由按顺序匹配,谁先定义谁的,谁优先级就高

2.路由嵌套

项目中最顶层都会有一个路由出口标签,同样的一个组件中也可以有自己的子路由出口
称为路由嵌套,需要在父路由属性中设置children。

new Router({
    routes[
        {
            path: '/tabs',
            component: Tabs,
            children:[
                {
                    path: 'home',
                    component: Home
                }
            ]
        }
    ]
})

chileren 就像是routes数组一样配置。所以你可以嵌套多个路由。
在父路由设置出口标签

const tabs = {
    template: '
        <h1>this is tabs</h1>
        <router-view></router-view>
        '
}

这样就可以使用 /tabs/home 来访问该路由了。 基于以上的配置此时访问 /tabs
是访问不到的,这是因为没有匹配的子路由。可以使用如下方法:

{
    path: '/tabs',
    component: Tabs,
    [
        {
            path: '',
            component: Home
        }
    ]
}

3.编程式导航

除了通过来创建a标签定义导航链接,
还可以通过router实例,来编写代码来实现导航。
在Vue实例内部,可以通过 r o u t e r 访 问 路 由 , 通 过 p u s h 方 法 , 来 实 现 编 程 导 航 t h i s . router访问路由,通过push方法,来实现编程导航 this. router访pushthis.router.push() 。
r o u t e r . p u s h , 会 向 h i s t o r y 添 加 一 个 新 记 录 , 当 用 户 点 击 浏 览 器 后 退 按 钮 时 , 则 回 到 之 前 的 U R L 。 当 使 用 < r o u t e r − l i n k t o = " " > 会 在 内 部 调 用 router.push,会向history添加 一个新记录,当用户点击浏览器后退按钮时, 则回到之前的URL。 当使用<router-link to="">会在内部调用 router.push,history退URL使<routerlinkto="">router.push()方法,
所以点击等同与调用$router.push()

router.push()

//字符串
const uid = 10
this.$router.push(`/list/${uid}`);     //     =>    /list/10
<router-link to="/list/10"></router-link>     //      =>     /list/10
//对象
this.$router.push({path: '/list/10'})    //    =>    /list/10
this.$router.push({path: '/list',params: { uid } })    //    =>    /list
this.$router.push({name: 'list', params: { uid } })    //    =>    /list/10
this.$router.push({path: `/list/${uid}`,query:{uid: uid}})    //    =>    /list/10?uid=12

这里需要注意的是: 使用path 会忽略name 属性 在 router-link :to="{}"标签中规则如上。

router.replace()

这里还提供一个方法 r o u t e r . r e p l a c e ( ) , 他 的 使 用 方 法 与 router.replace(),他的使用方法与 router.replace(),使router.push() 无异。
唯一不同的是他不会向history添加新记录,而是替换掉当前的history记录。

router.to()
这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步。
router.go(1) //前进一步
router.go(-1) //后退

4.路由重定向和别名

1.重定向

重定向是通过routes配置完成的,下面还是看tabs的实例

 new Router({
        routes:[
            {
                path:'/tabs'
                component: Tabs,
                children:[
                    {
                        path:'home',
                        component: Home
                    },
                    {   ...   },
                ]
            }
        ]
    })

以上父路由tabs,子路由home。要想访问子路由home。访问地址为/tabs/home。
我们要想进入/tabs时默认访问home组件。上面路由嵌套部分给出的是,子路由为空

   children:[
        {
            path:'',
            component: Home
        }
   ]

这里我们使用重定向:

   new Router({
        routes:[
            {
                path:'/tabs'
                component: Tabs,
                redirect: '/tabs/home'
                children:[
                    {
                        path:'home',
                        component: Home
                    }
                ]
            }
        ]
    })

我们直接输入地址 /tabs 会发现直接进入到 /tabs/home

以下有三种方式:

redirect:''
redirect:{name: ''}
redirect: to=>{
    // 方法接收 目标路由 作为参数
    // return 重定向的 字符串路径/路径对象
}
2.别名

“重定向”的意思是,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b,
那么“别名”又是什么呢?
/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,
就像用户访问 /a 一样。
上面对应的路由配置为:

 new Router({
        routes:[
            {
                path:'/tabs'
                component: Tabs,
                children:[
                    {
                        path:'home',
                        component: Home,
                        alias:''
                    }
                ]
            }
        ]
    })

还是tabs的例子,这里我们给默认展示的子路由,起一个空别名,
当我们访问/tabs 就会匹配到home的别名。就会访问/tabs/home组件。

5.路由组件传参

使用$route会使其形成高度耦合,在指定的URL上使用,限制了其灵活性。

$route的耦合
var user = {
    template:'<div>{{$route.params.id}}</div>'
}
var router = new Router({
    routes:[
        {
            path:'/user/:id',
            component: User
        }
    ]
})
通过props解耦合
  var user = {
        props:[''id],
        template:'<div>{{id}}</div>'
    }
    var router = new Router({
        routes:[
            {
                path:'/user/:id',
                component: User,
                props:true
            },
            //对象包含命名视图的路由,你必须分名添加props
            {
                path:'/user/:id',
                components:{
                    default:User,
                    sidebar: Sidebar
                },
                props:{
                    default: true,
                    sidebar: false
                }
            }
        ]
    })

如果 props 被设置为 true,route.params 将会被设置为组件属性

6.导航守卫

‘导航’表示路由正在发生变化
**参数/查询字符的变化触发 进入/离开的导航守卫。可以通过$route的变化,或者beforeRouteUpdated
的组件内的守卫。

一、全局守卫

1、全局前置守卫

当一个导航触发时。全局前置守卫按照茶创建顺序调用 。守卫是异步解析执行的,
此时所有导航守卫resolve完之前一直处于等待中。

routre.beforeEach((to,from,next)=>{

})

每个守卫都接受三个参数:
to: Route :即将进入的目标路由
from: Route :当前导航要离开的路由
next: Function :一定要调用这个方法resolve这个钩子函数,
next() :确认执行。
next(false) :中断执行。
next(’/’)或者next({path: ‘/’}) :跳到一个不同的地址。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,
则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
确保要使用next方法,resolve。否则导航一直会处于等待状态。

2、全局解析守卫

注册全局解析钩子,router.beforeResolve(),这和rouer.beforeEach 类似。
区别是导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

router.beforeResolve((to,from,next)=>{

})
3、全局后置钩子

注册全局后置钩子,router.afterEach()和守卫不同的是,这些钩子不会接受next,也不会改变导航本身。

router.afterEach((to,from)=>{

})

二、路由独享守卫

可以在路由配置上直接定义 beforeEnter。

new Router({
    routes:[
        {
            path:'/',
            component: ...,
            beforeEnter: (to,from,next)=>{

            }
        }
    ]
})

参数与全局前置守卫一样router.beforeEach

三、组件内的守卫

最后还可以在组件内直接使用路由导航守卫

beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const Foo = {
    template: '...',
    beforeRouteEnter(to,from,next) {
        //在组件渲染被confirm前调用
        // 这你 不能组件实例获取  this
        //因为调用当前守卫时,组件实例还没有被创建
    },
    beforeRouteUpdate(to,from,next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    },
    beforeRouteLeave(to,from,next) {
        //导航离开组件时调用
        // 可以访问组件实例 `this`
    }
}
1、beforeRouteEnter:

不能范围组件实例,因为在导航确认之前调用,组件还未被创建。
不过可以通next回调来访问组件实例。在导航被确认的时候执行回调。
并把组件实例作为回调参数

beforeRouteEnter(to,from,next){
    next(vm=>{
        //通过vm范围组件实例
    })
}

注意 beforeRouteEnter 是支持给 next 传递回调的唯一守卫。
对于 beforeRouteUpdate 和 beforeRouteLeave 来说,
this 已经可用了,所以不支持传递回调,因为没有必要了。

2、beforeRouteUpdate:

同一组件复用,并不会触发,生命周期。动态路由参数提到了,两中方法。
监听$route变化,和使用 beforeRouteUpdate。

beforeRouteUpdate(to,from,next){
    this.name = to.params.name
    next()
}
3、beforeRouteLeave:

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

beforeRouteLeave (to, from, next) {
    const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
    if (answer) {
        next()
    } else {
        next(false)
    }
}

路由守卫一览:


//全局守卫
router.beforeEach((to,from,next)=>{

})
router.beforeResolve((to,from,next)=>{

})
router.afterEach((to,from)=>{

})
//局部守卫
new Router({
    routes:[
        {
            path:'/any',
            component:...,
            beforEnter:((to,from,next)=>{

            })
        }
    ]
})
//组件守卫
beforeRouteEnter(to,from,next){

}
beforeRouteUpdate(to,from,next){

}
beforeRouteLeave(to,from,next){

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值