vueファミリーバケツ(vue-router簡版ソースコードの実現)


vue-router
Vue RouterはVueです.js官方のルーティングマネージャ.Vueとjsのコア深度統合により、単一ページアプリケーションの構築が容易になります.
  • ネストされたルーティング/ビューグラフ
  • モジュール化コンポーネントベースのルーティング構成
  • ルーティングパラメータ、クエリー、ワイルドカード
  • はVueに基づく.js遷移システムのビュー遷移効果
  • 細粒度のナビゲーション制御
  • 自動アクティブCSS class付きリンク
  • HTML 5履歴モードまたはhashモード、IE 9で
  • を自動的に降格
  • カスタムスクロールバー動作
  • インストール:vue add router
    コアステップ:
    手順一:vue-routerプラグイン、routerを適用する.js
    import Router from 'vue-router'
    Vue.use(Router)
    

    ステップ2:ルーティングテーブルを宣言する(マッピングテーブルであり、pathとコンポーネントはマッピング関係である)
    const routes = [
      {
         
        path: '/',
        name: 'Home',
        component: Home
      },
      {
         
        path: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
      }
    ]
    

    手順3:Routerインスタンス、routerを作成します.js(そしてエクスポート)
    const router = new VueRouter({
         
      mode: 'history',
      base: process.env.BASE_URL,
      routes
    })
    

    ステップ4:ルートコンポーネントにインスタンスを追加するmain.js
    import router from './router'
    new Vue({
         
        router,
    }).$mount("#app")
    

    ステップ5:ルーティングビュー、Appを追加する.vue
    <router-view></router-view>
    

    ナビゲーションリンク
    <router-link to="/">Home</router-link> 
    <router-link to="/about">About</router-link>
    

    以上は多分vue-routerの基本的な使用で、以下は簡略版のソースコードの実現部分に入ります
    vue-routerソース実装
    需要分析
  • spaページはリフレッシュできません
  • hash方式例えば#/home
  • またはHistory api例:/about
  • urlに従って対応するコンテンツを表示
  • router-view
  • データ応答式:current変数はurlアドレスを持ち、変化するとrender
  • を動的に再実行する.

    タスク#タスク#
  • プラグインを実装(VueRouterクラスとinstallスキーマの作成)
  • VueRouterクラスの実装
  • 処理ルーティングオプション
  • urlの変化をモニタ
  • 相応の変化
  • installメソッドを実装
  • $routerの登録
  • の2つのグローバルコンポーネント


  • kvue-routerを作成します.js
    let Vue; //       ,VueRouter    
    //     
    class VueRouter {
         
       constructor(options) {
         
         this.$options = options;
       }
    }
    //   :  install  ,  $router
    VueRouter.install = function(_Vue) {
         
      //       ,VueRouter    
      Vue = _Vue;
      //   1:  $router
      Vue.mixin({
         
    	beforeCreate() {
         
    	  //        router  
    	  if (this.$options.router) {
         
    	  // vm.$router
    	    Vue.prototype.$router = this.$options.router;
    	  }
    	}
      });
      //   2:        router-link router-view
      Vue.component('router-link', Link)
      Vue.component('router-view', View)
    };
    export default VueRouter;
    
    ? use ,Router , install , ( )
    router-viewとrouter-linkの作成
    krouter-linkを作成します.js
     export default {
         
        //        
        props: {
         
          to: {
         
            type: String,
            require: true
          }
        },
        render(h) {
         
          // 
          // XXX
          //      
          return h('a',{
         
            attrs: {
         
              href: '#' + this.to
            }
          }, this.$slots.default)
          //         jsx
          // return {this.$slots.default}
        }
      }
    

    krouter-viewを作成します.js
    export default {
         
      render(h) {
         
      //           
        return h(null);
      }
    }
    

    urlの変化を監視応答式のcurrent属性を定義しhashchangeイベントを傍受する
    class VueRouter {
         
      constructor(options) {
         
      // current       
      Vue.util.defineReactive(this, 'current', '/')
      //         current
      const initial = window.location.hash.slice(1) || '/'
      Vue.util.defineReactive(this, 'current', initial)
        //   hashchange  
        window.addEventListener('hashchange', this.onHashChange.bind(this))
        window.addEventListener('load', this.onHashChange.bind(this))
      }
      onHashChange() {
          
        this.current = window.location.hash.slice(1)
     }
    }
    

    対応するコンポーネントを動的に取得するkrouter-view.js
    export default {
         
      render(h) {
         
      //         
        let component = null;
        this.$router.$options.routes.forEach(route => {
         
        if (route.path === this.$router.current) {
         
          component = route.component
        } 
       });
       return h(component);
      }
    }
    

    事前処理ルーティングテーブル事前処理ルーティングテーブル毎回ループを避ける
    class VueRouter {
         
      constructor(options) {
         
    	//   path route    
    	this.routeMap = {
         }
    	this.$options.routes.forEach(route => {
         
    	  this.routeMap[route.path] = route
    	});
      }
    }
    

    使用するjs
    export default {
         
      render(h) {
         
        const {
         routeMap, current} = this.$router
        const component = routeMap[current] ? routeMap[current].component : null;
        return h(component);
      }
    }
    

    完全なコードを添付します
    //       
    // 1.       
    // 2.         ,    install  
    
    
    let _Vue = null
    /**
     * @class VueRouter
     * @param options   
     */
    
    class VueRouter {
         
      constructor(options) {
         
        // options     : router -    
        this.$options = options
    
        //   path  route     
        this.routeMap = {
         }
    
         //     url     
        this.$options.routes.forEach(route => {
         
          this.routeMap[route.path] = route
        })
    
        //           current  
        const initial = window.location.hash.slice(1) || '/'
        // defineReactive             
        _Vue.util.defineReactive(this, 'current', initial)
    
        //   url   
        window.addEventListener('hashchange', this.onHashChange.bind(this))
    
      }
      onHashChange () {
         
        this.current = window.location.hash.slice(1)
        console.log(this.current)
      }
    }
    
    VueRouter.install = function(Vue) {
         
      //   Vue    ,    VueRouter   
      _Vue= Vue
      // 1.   $router
      //     ,    
      Vue.mixin({
         
        //    this    vue   
        beforeCreate() {
         
          if(this.$options.router) {
         
            Vue.prototype.$router = this.$options.router
          }
        }
      })
    
      // 2.         router-link, router-view
      Vue.component('router-link', {
         
        //        
        props: {
         
          to: {
         
            type: String,
            require: true
          }
        },
        render(h) {
         
          // 
          // XXX
          //      
          return h('a',{
         
            attrs: {
         
              href: '#' + this.to
            }
          }, this.$slots.default)
          //         jsx
          // return {this.$slots.default}
        }
      })
      Vue.component('router-view', {
         
        render(h) {
         
          //      url     
          const {
          routeMap, current } = this.$router
          const component = routeMap[current] ? routeMap[current].component : null
          return h(component)
        }
      })
    }
    
    export default VueRouter