// routes注册 import Vue from "vue"; // import VueRouter from "vue-router"; import VueRouter from "./vueRouter"; // 自定义路由 js import Home from "../views/Home.vue"; Vue.use(VueRouter); const routes = [ { path: "/", name: "Home", component: Home, }, { path: "/about", name: "About", // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ "../views/About.vue"), }, ]; const router = new VueRouter({ mode: "history", routes, }); export default router;
// vueRouter var _Vue = null export default class VueRouter { // 一、 install方法 static install(Vue) { // 1、判断插件是否注册 if (VueRouter.install.installed) return VueRouter.install.installed = true // 2、将Vue构造函数记录到全局变量 _Vue = Vue // 3、把创建Vue实例的时候传入的router对象注入到Vue实例上 // _Vue.prototype.$router = this.$options.router; // 混入 _Vue.mixin({ beforeCreate() { if (this.$options.router) { _Vue.prototype.$router = this.$options.router this.$options.router.init() // ? } } }) } // 二、构造函数 constructor(options) { this.options = options this.routeMap = {} this.data = _Vue.observable({ current: '/' }) } init() { this.createRouteMap() this.initComponents(_Vue) this.initEvent() } // 三、createRouteMap createRouteMap() { // 遍历所有的路由规则,把路由规则解析成键值对,保存在routeMap中 this.options.routes.forEach(route => { this.routeMap[route.path] = route.component }) } // 四、initComponents initComponents(Vue) { Vue.component('router-link', { props: { to: String }, // template: '<a :href="to"><slot></slot></a>' render(h) { return h( 'a', { attrs: { href: this.to }, on: { click: this.clickHandler } }, [this.$slots.default] ) }, methods: { clickHandler(e) { history.pushState({}, '', this.to) // 修改地址栏 - 不会发送请求 this.$router.data.current = this.to // 重新加载响应的组件 e.preventDefault() // 阻止发送请求 } } }) const self = this Vue.component('router-view', { render(h) { let component = self.routeMap[self.data.current] return h(component) } }) } // 五、返回按钮、前进按钮问题 initEvent() { window.addEventListener('popstate', () => { this.data.current = window.location.pathname }) } }
一、普通、动态路由传参方式
// 路由代码传参 import About from 'about' // routes 配置 { path: '/about/:id', // 动态路由 component: About, props: true // ①布尔模式 } { path: '/about', // 普通路由 component: 'About', props: { id: 19 } // ②对象模式 } // 接收方式 props props;['id'] 或者 props: { id: { type: Number, default: 12} } // ③函数模式 routes:[ { path: '/about', component: About, // props: route => ({id:route.query.id}) // url='/about?id="89"' 或者 props: route => ({id: route.params.id}) // url='/about/:id' => '/about/89' } ]
二、动态路由:将给定匹配模式的路由映射到同一个组件,复用一个组件,相对与销毁后重建更高效。
Keep-alive包括时,组件的声明周期钩子函数不会被重复调用。
要对同一个组件中参数变化做出响应的话,可以通过watch 侦听$route对象上的任意属性
watch: { $route: { immediate: true, handler(route) { // 处理事件 对路由变化做出响应 } } }
或者使用导航守卫,beforeRouteUpdate,也可以取消导航
三、捕获所有路由或404路由
四、路由的匹配语法
自定义正则 像可以区分 /list/100 和/list/xsk 等路由
可以重复的参数 匹配多个部分的路由,可以用 * 号和 +号将参数标记为重复
也可通过使用?号修饰符(0个或1个)将一个参数标记为可选
五、嵌套路由、命名路由
六、编程式导航
声明式(
Router.push(params):
Params: 字符串路径、路径对象、命名的路由并加上参数、带查询参数、带hash
'/users/detail' { path: '/users/detail' } { name: 'detail', params: {id: '0'}} { path: '/users/detail', query: {id: '0'} }
替换当前位置 router.replace({path: '/users'}) 或者router.push({path:'users', replace: true}); 导航时不会向history添加记录
history.go()横跨历史
七、命名视图:
八、重定向配置
// 通过routes配置来完成 const routes = [{ path: '/home', redirect: '/'}] // 重定向的目标也可以是一个命名的路由 redirect: { name: 'Details'} // 一个方法动态返回重定向目标 const routes = [ { path: '/home/:id', redirect: to => { return {path:'Details', query: { q: to.params.searchText}} } } ] // 别名 alias: '/home'
九、路由组件传参 props、$route.query$route.params
布尔模式 routes配置时 props:true设置即可
对象模式 props: { id: '0' } 当props为静态的时候很有用
函数模式 创建一个返回props的函数,允许你将参数转换为其他类型,将静态值与基于路由的值相结合等操作
props: route => ({ query: route.query.id }) props: route => ({ params: route.params.id})
对于命名视图的路由,必须为每个命名视图定义props配置
const routes = [{ path: '/home', components: { default: Home, sidebar: Sidebar}, props: { default: true, sidebar: true} }]
十、不同的历史模式
一、导航守卫:vue-router提供的主要是通过跳转或取消的方式守卫导航。
方式:全局、单个路由独享、组件
全局前置守卫:beforeEnter:
全局后置守卫:afterEach 不接受next函数也不会改变导航本身
全局解析守卫:beforeResolve
路由独享守卫:在routes中配置
组件内的守卫 可用配置API:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave