路由
用 Vue.js + Vue Router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 Vue Router 添加进来,我们需要做的是,将组件 (components) 映射到路由 (routes),然后告诉 Vue Router 在哪里渲染它们
起步
<!DOCTYPE html>
<html lang="en">
<head>
<script src="../vue.js"></script>
<script src="../vue-router.js"></script>
<style>
.router-link-exact-active{
color: red;
}
</style>
</head>
<body>
<div id="app">
<ul>
<router-link to="/position">职位</router-link>
<router-link to="/search">搜索</router-link>
</ul>
<router-view></router-view>
</div>
<script>
const position = {
template:`<div>position</div>`
}
const search = {
template:`<div>search</div>`
}
var router = new VueRouter({
mode:'hash',
routes:[
{
path:"/",
redirect: '/position'
},
{
path:'/position',
component:position
},
{
path:'/search',
component:search
}
]
})
var vm = new Vue({
router,
el:"#app",
})
</script>
</body>
</html>
动态路由
<!DOCTYPE html> <html lang="en"> <head> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-exact-active { color: red; } </style> </head> <body> <div id="app"> <router-link tag="div" to="/position/35">职位</router-link> <router-link tag="div" to="/search">搜索</router-link> <router-view></router-view> </div> <script> const search = { template: `<div>search</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position/:id', //动态路由 component: { template: `<div>{{$route.params}} </div>` //$route.params等于{ "id": "35" } } }, { path: '/search', component: search }, ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
嵌套路由
<!DOCTYPE html> <html lang="en"> <head> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active{ color: red; } </style> </head> <body> <div id="app"> <ul> <router-link to="/position">职位</router-link> <router-link to="/search">搜索</router-link> </ul> <router-view></router-view> </div> <script> const position ={template:`<div> <router-link to="/position/fe">前端</router-link> <router-link to="/position/be">后端</router-link> <router-view></router-view> </div>` } const search = { template:`<div>search</div>` } var router = new VueRouter({ mode:'hash', routes:[ { path:'/position', component:position, children:[ //嵌套路由 { path:'fe', component:{ template:`<div>position fe</div>` } }, { path:'be', component:{ template:`<div>position be</div>` } } ] }, { path:'/search', component:search } ] }) var vm = new Vue({ router, el:"#app", }) </script> </body> </html>
编程式导航
<!DOCTYPE html> <html lang="en"> <head> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active{ color: red; } </style> </head> <body> <div id="app"> <ul> <router-link to="/position">职位</router-link> <router-link to="/search">搜索</router-link> </ul> <router-view></router-view> <button @click="go">编程式导航</button> </div> <script> const position ={ template:`<div>position</div>` } const search = { template:`<div>search</div>` } var router = new VueRouter({ mode:'hash', routes:[ { path:'/position', component:position, }, { path:'/search', component:search } ] }) var vm = new Vue({ router, el:"#app", methods:{ go(){ // this.$router.push('/position') //这这两种写法都行, 编程式导航 this.$router.push({ path:'/position' }) } } }) </script> </body> </html>
命名路由
意思是用name标示路由
<!DOCTYPE html> <html lang="en"> <head> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active{ color: red; } </style> </head> <body> <div id="app"> <ul> <router-link :to="{name:'ps'}">职位</router-link> //使用名字访问路由 <router-link to="/search">搜索</router-link> </ul> <router-view></router-view> </div> <script> const position ={ template:`<div>position</div>` } const search = { template:`<div>search</div>` } var router = new VueRouter({ mode:'hash', routes:[ { path:'/position', name:'ps', //命名路由 component:position, }, { path:'/search', component:search } ] }) var vm = new Vue({ router, el:"#app", }) </script> </body> </html>
命名视图
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有
sidebar
(侧导航) 和main
(主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果router-view
没有设置名字,那么默认为default
<!DOCTYPE html> <html lang="en"> <head> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active{ color: red; } </style> </head> <body> <div id="app"> <ul> <router-link to="/position">职位</router-link> <router-link to="/search">搜索</router-link> </ul> <router-view name="header"></router-view> //命名视图 @key <router-view ></router-view> <router-view name="footer"></router-view> </div> <script> const position ={ template:`<div>position</div>` } const search = { template:`<div>search</div>` } var router = new VueRouter({ mode:'hash', routes:[ { path:'/position', components:{ default:{template:'<div>main content</div>'}, //模版和命名视图名字对上 @key header:{template:'<div>header content</div>'}, footer:{template:'<div>footer content</div>'} } }, { path:'/search', component:search } ] }) var vm = new Vue({ router, el:"#app", }) </script> </body> </html>
路由组件传参
在组件中使用 $route
会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。
使用 props
将组件和路由解耦
布尔模式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position/35">职位</router-link> <router-view></router-view> </div> <script> const position = { props: ['id'], template: `<div>position {{id}}</div>` // 这块输出: position 35 } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position/:id', component: position, props: true, //@key } ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
对象模式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position">职位</router-link> <router-view></router-view> </div> <script> const position = { props: ['uname','age'], //@Key template: `<div>{{uname}}-{{age}}</div>` //这块输出:hanye-20 } const search = { template: `<div>search</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position', component: position, props:{uname:'hanye',age:20}, //@key }, { path: '/search', component: search } ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
函数模式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/search?keyword=前端">搜索</router-link> <router-view></router-view> </div> <script> const search = { props: ['query'], //@Key template: `<div>参数:{{query}}</div>` //参数:前端 } var router = new VueRouter({ mode: 'hash', routes: [ { path: '/search', component: search, props:(route)=>{ return {query:route.query.keyword}} //@key } ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
导航守卫
导航守卫其实也是路由守卫,也可以是路由拦截,我们可以通过路由拦截,来判断用户是否登录,该页面用户是否有权限浏览,就是拦截器,类似钩子之类的。。。
全局路由守卫有2个
- <span style="color:red">全局前置守卫</span> 应用场景:例如判断用户是否登录之类的
- <span style="color:red">全局后置守卫</span>
每个守卫方法接收三个参数:
to: Route
: 到哪个页面去from: Route
: 从哪个页面来next: Function
:next()
: 进行管道中的下一个钩子next(false)
: 中断当前的导航next('/')
或者next({ path: '/' })
: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next
传递任意位置对象,且允许设置诸如replace: true
、name: 'home'
之类的选项以及任何用在router-link
的to
prop 或router.push
中的选项。next(error)
: (2.4.0+) 如果传入next
的参数是一个Error
实例,则导航会被终止且该错误会被传递给router.onError()
注册过的回调。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position?islogin=1">职位</router-link> <router-link to="/login">登录</router-link> <router-view></router-view> </div> <script> const position = { template: `<div>职位页面</div>` } const search = { template: `<div>登录页面</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position', component: position, }, { path: '/login', component: search } ] }) //@key 全局前置守卫 router.beforeEach((to, from, next) => { if(to.path == "/login") { //除了`/login`路由不需要判断,其余路由都需要判断 next() } else { if (to.query.islogin !=0) { //1 代表登录, 0 代表没有登录 next() } else { next('/login') } } }) //@key 全局后置守卫 router.afterEach((to,from)=>{ console.log("afterEach") alert(1) }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
路由独享守卫
路由独享守卫是在路由配置页面单独给路由配置的一个守卫
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position?islogin=1">职位</router-link> <router-link to="/login">登录</router-link> <router-view></router-view> </div> <script> const position = { template: `<div>职位页面</div>` } const search = { template: `<div>登录页面</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position', component: position, beforeEnter:(to,from,next)=>{ //@key 路由守卫 console.log('路由守卫'); next() } }, { path: '/login', component: search } ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
组件内守卫
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position?islogin=1">职位</router-link> <router-link to="/login">登录</router-link> <router-view></router-view> </div> <script> const position = { template: `<div>职位页面</div>`, beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 next() }, beforeRouteUpdate(to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave(to, from, next) { //这个离开守卫通常用来禁止用户在还未保存修改前突然离开, //该导航可以通过 next(false) 来取消。 // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` let rs = confirm("确认要离开么?") if (rs) { next() } } } const search = { template: `<div>登录页面</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position', component: position, }, { path: '/login', component: search } ] }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html>
路由元信息
就是可以给路由配置一些参数,例如,哪些路由判断是否登录,哪些路由不判断路由验证
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <style> .router-link-active { color: red; } </style> </head> <body> <div id="app"> <router-link to="/position?islogin=1">职位</router-link> <router-link to="/login">登录</router-link> <router-view></router-view> </div> <script> const position = { template: `<div>职位页面</div>` } const search = { template: `<div>登录页面</div>` } var router = new VueRouter({ mode: 'hash', routes: [{ path: '/position', component: position, meta:{ //@key 通过meta字段进行配置 auth:true } }, { path: '/login', component: search } ] }) router.beforeEach((to, from, next) => { if(to.meta.auth == true){ //@Key console.log('请您先登录'); } next() }) var vm = new Vue({ router, el: "#app", }) </script> </body> </html