class SimpleVueRouter {}
SimpleVueRouter.install = function(_Vue) { // Vue是js内部的变量,_Vue是真正的Vue类 Vue = _Vue; }
class SimpleVueRouter { constructor(options) { this.$options = options; this.routeMap = {}; this.app = new Vue({ data() { return { current: '/' } } }); } }
// 添加install方法,在Vue.use的时候会执行 SimpleVueRouter.install = function(_Vue) { Vue = _Vue; Vue.mixin({ beforeCreate() { /** * this是Vue的实例对象 * this.$options是new Vue()的时候传入的参数 * 只有main.js才会有router这个项,因此if只会进入一次 * */ if (this.$options.router) { this.$router = this.$options.router; this.$options.router.init(); } } }); }
initEvent() { // 监听浏览器的hashchange和load事件,使用bind改变this指向 window.addEventListener('hashchange', this.handleHashChange.bind(this)); window.addEventListener('load', this.handleHashChange.bind(this)); } handleHashChange() { // 获取#后面的部分赋值给app的current this.app.current = location.hash.slice(1); }
initRouteMap() { this.$options.routes.forEach(item => { this.routeMap[item.path] = item; }); }
registerComponents() { Vue.component('s-router-link', { props: { to: String }, render: function (h) { return h('a', { attrs: { href: `#${this.to}` } }, this.$slots.default); } }); Vue.component('s-router-view', { render: h => { // 此处使用箭头函数,为了让this指向当前router实例而不是vue实例 const com = this.routeMap[this.app.current].component; return h(com) } }); }
init() { this.initEvent(); this.initRouteMap(); this.registerComponents(); }
import SimpleVueRouter from './simple-vue-router'; import Vue from 'vue'; import Com1 from './components/com1'; import Com2 from './components/com2'; import Home from './components/home'; Vue.use(SimpleVueRouter); export default new SimpleVueRouter({ routes: [{ path: '/', component: Home }, { path: '/com1', component: Com1 }, { path: '/com2', component: Com2 }] });
<template> <div id="app"> <s-router-link to="/com1">com1</s-router-link> <s-router-link to="/com2">com2</s-router-link> <s-router-view></s-router-view> </div> </template> <script> export default { } </script> <style> </style>
整个思路流程就是,注册插件,监听浏览器的hash改变事件,当hash改变的时候,修改某个vue实例的某个属性,利用vue的响应式,使用到的地方也会改变,从而去更新router-view显示的地方 html
本例只实现了使用hash的方式的实现简单的路由跳转和显示,其余方法读者有兴趣的话能够本身实现vue