Vue-Router
vue-router是vue的核心插件,vue+vue-router 主要来做 SPA(Single Page Application) 单页面应用
为什么要使用单页面应用?
传统的路由跳转,如果后端资源过多,会导致页面出现`白屏现象`,让前端来做路由,在某个生命周期的钩子函数中发送ajax,数据驱动。为了用户体验
官网
https://router.vuejs.org/zh/installation.html
安装
直接下载 / CDN
https://unpkg.com/vue-router/dist/vue-router.js
项目中下载指定版本
cnpm i vue-router@2 -S
1.定义路由组件
const Home = { data() { return {} }, template: `<div>我是首页</div>` }
2.创建router实例,配置路由规则
const router = new VueRouter({ //定义路由规则 mode:'history', routes: [ { path:'/', redirect:'/home' }, { path: '/home', component: Home }, { path: '/course', component: Course } ] })
3.创建Vue实例,并挂载路由对象
new Vue({ el: '#app', //挂载 路由对象 router, data() { return {} }, template: `<App />`, components: { App } })
4.template中渲染router-link和router-view
let App = { data() { return {} }, // router-link和router-view 是vue-router 提供的两个全局组件 //router-view 是路由组件的出口 //router-link默认会被渲染成a标签,to属性默认被渲染成href template: ` <div> <div class="header"> <router-link to = '/home'>首页</router-link> <router-link to = '/course'>免费课程</router-link> </div> <router-view></router-view> </div> ` }
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> </div> <script src="vue.js"></script> <script src="vue-router.js"></script> <script> //如果以后是模块化编程,Vue.proptotype.$VueRouter = VueRouter // Vue.use(VueRouter) const Home = { data() { return {} }, template: `<div>我是首页</div>` } const Course = { data() { return {} }, template: `<div>我是免费课程</div>` } //创建路由 const router = new VueRouter({ //定义路由规则 mode:'history', routes: [ { path:'/', redirect:'/home' }, { path: '/home', component: Home }, { path: '/course', component: Course } ] }) let App = { data() { return {} }, // router-link和router-view 是vue-router 提供的两个全局组件 //router-view 是路由组件的出口 template: ` <div> <div class="header"> <router-link to = '/home'>首页</router-link> <router-link to = '/course'>免费课程</router-link> </div> <router-view></router-view> </div> ` } new Vue({ el: '#app', //挂载 路由对象 router, data() { return {} }, template: `<App />`, components: { App } }) </script> </body> </html>
命名路由
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes
配置中给某个路由设置名称。
要链接到一个命名路由,可以给 router-link
的 to
属性传一个对象:
注意需要绑定 :to
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> </div> <script src="vue.js"></script> <script src="vue-router.js"></script> <script> const Home = { data() { return {} }, template: `<div>我是首页</div>` } const Course = { data() { return { categoryList:[] } }, template: `<div> <span v-for = '(item,index) in categoryList'>{{item.name}}</span> </div>`, methods:{ getCategroyList(){ } }, created(){ //ajax 发送请求 数据获取 this.getCategroyList(); } } //创建路由 const router = new VueRouter({ //定义路由规则 routes: [ { path:'/', redirect:'/home' }, { path: '/home', name:'Home', component: Home }, { path: '/course', name:'Course', component: Course } ] }) let App = { data() { return {} }, // router-link和router-view 是vue-router 提供的两个全局组件 //router-view 是路由组件的出口 template: ` <div> <div class="header"> <router-link :to = '{name:"Home"}'>首页</router-link> <router-link :to = '{name:"Course"}'>免费课程</router-link> </div> <router-view></router-view> </div> ` } new Vue({ el: '#app', //挂载 路由对象 router, data() { return {} }, template: `<App />`, components: { App } }) </script> </body> </html>
动态路由匹配
$route 路由信息对象
提醒一下,当使用路由参数时,例如从 /user/foo
导航到 /user/bar
,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
这里我们使用watch (监测变化) $route
对象:
$route(to,from) 这两个参数,to 代表到哪里去 , from 代表你从哪里来
1.动态绑定参数
2.router-link绑定这个对象
3.watch监听路由变化
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <div id="app"> </div> <script src="vue.js"></script> <script src="vue-router.js"></script> <script> //如果以后是模块化编程,Vue.proptotype.$VueRouter = VueRouter // Vue.use(VueRouter) //路由范式: //http://127.0.0.1:8080/index/user //http://127.0.0.1:8080/user/1 params //http://127.0.0.1:8080/user/2 //http://127.0.0.1:8080/user?user_id =1 query const User = { data() { return { user_id:null } }, template: `<div>我是用户{{ user_id}}</div>`, created() { console.log(this.$route); //路由信息对象 // 提醒一下,当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。 }, watch: { '$route'(to, from) { // 对路由变化作出响应... console.log(to.params.id); console.log(from); this.user_id = to.params.id; //发送ajax } } } //创建路由 const router = new VueRouter({ //定义路由规则 routes: [ { path: '/user/:id', name: 'User', component: User } ] }) let App = { data() { return {} }, // router-link和router-view 是vue-router 提供的两个全局组件 //router-view 是路由组件的出口 template: ` <div> <div class="header"> <router-link :to = '{name:"User",params:{id:1}}'>用户1</router-link> <router-link :to = '{name:"User",params:{id:2}}'>用户2</router-link> </div> <router-view></router-view> </div> ` } new Vue({ el: '#app', //挂载 路由对象 router, data() { return {} }, template: `<App />`, components: { App } }) </script> </body> </html>
query
编程式导航
$router 路由对象 VueRouter
标签绑定事件后,使用$router.push进行跳转
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="../vue.js"></script> <script src="../vue-router.js"></script> <div class="app"> </div> <div></div> <script> const Home = { data(){ return{} }, template: `<div>我是首页</div> ` }; const User = { data(){ return{ user_id:null } }, template: `<div>我是用户{{ user_id }}号 <button @click="clickHankler">跳转首页</button> </div> `, methods:{ //编程式导航 clickHankler (){ this.$router.push({ name:'Home' }) } }, watch:{ '$route'(to,from) { // console.log(to); console.log(from); this.user_id = to.params.id } } }; const router = new VueRouter({ mode:"history", routes:[ { path:'/user/:id', component: User, name:'user' }, { path:'/home', component:Home, name:'Home' } ], }); let App = { data(){ return{} }, template:` <div> <router-link :to="{name:'user',params:{id:1}}">用户1</router-link> <router-link :to="{name:'user',params:{id:2}}">用户2</router-link> <router-view></router-view> </div> ` }; new Vue({ el:'.app', router, data(){ return{ } }, template:`<App/>`, components:{ App } }) </script> </body> </html>
获取原生的DOM的方式
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="../vue-router.js"></script> <script src="../vue.js"></script> <div id="app"> </div> <div></div> <script> Vue.component('Test', { data() { return {} }, template: `<div>我是测试组件</div> ` }); let App = { data() { return {} }, template: ` <div ref="abc"> <Test ref="zzz"></Test> </div> `, mounted() { // console.log(this.$refs); // console.log(this.$refs.abc); // console.log(this.$refs.zzz); // console.log(this.$refs.zzz.$parent); // console.log(this.$refs.zzz.$root); //找到Vue实例对象 // console.log(this.$refs.zzz.$children) } }; new Vue({ el: '#app', data() { return {} }, components: { App }, template:` <App></App> ` }) </script> </body> </html>
全局前置守卫
你可以使用 router.beforeEach
注册一个全局前置守卫:
当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于 等待中。
每个守卫方法接收三个参数:
-
to: Route
: 即将要进入的目标 路由对象 -
from: Route
: 当前导航正要离开的路由 -
next: Function
: 一定要调用该方法来 resolve 这个钩子。执行效果依赖next
方法的调用参数。-
next()
: 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。 -
next(false)
: 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到from
路由对应的地址。 -
next('/')
或者next({ path: '/' })
: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向next
传递任意位置对象,且允许设置诸如replace: true
、name: 'home'
之类的选项以及任何用在router-link
的to
prop 或router.push
中的选项。 -
next(error)
: (2.4.0+) 如果传入next
的参数是一个Error
实例,则导航会被终止且该错误会被传递给router.onError()
注册过的回调。
-
**确保 next
函数在任何给定的导航守卫中都被严格调用一次。它可以出现多于一次,但是只能在所有的逻辑路径都不重叠的情况下,否则钩子永远都不会被解析或报错。**这里有一个在用户未能验证身份时重定向到 /login
的示例: