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