原則として、ルートVUE

ルーティングルーティングのフロントエンドとバックエンドへのルート、最初はそれは、バックエンドのルーティングがあるが、ルーティングスイッチは、ページを更新する必要がありますたびに、要求を送信し、サーバーが返すデータ、ユーザ体験は良いではない、と後の前に現れましたルーティング、それはことを特徴としているブラウザで更新されません。

フロントエンドは、二つの経路、ハッシュモード、履歴モードに分割されています

履歴ルーティング原理

  1. プロジェクトに初めて、解決のURLに持って、対応するルーティングをロード

  2. このプロジェクトは、ルートを切り替える必要がロードされています。:あなたは、ラベルスイッチング、JSを使用してプッシュ方式が切り替えた場合、デフォルトのイベントを防止する必要性、直接操作を使用している場合

    1. window.history.pushState:閲覧履歴のレコードの増加
    2. window.history.replaceState:replaceState後のアドレスに現在のブラウザのアドレス、一定の閲覧履歴の長さの合計
    3. onpopstateウィンドウオブジェクトがスタックの歴史の中で、モニタの変化への方法を持っている限り、変更があったとして、それはイベントをトリガします
    4. ブラウザで提供される方法上記H5は更新されません

歴史回路図.PNG

コードの実装:

main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router: router,
  render: h => h(App)
}).$mount('#app')
router.js
import Vue from 'vue'
import VueRouter from './vue-router'
import Home from './views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/home',
    name: 'home',
    component: Home
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
  }
]

const router = new VueRouter({
  routes
})

export default router
index.js VUE-ルータフォルダ
let Vue = null;

export default class Router{
  static install(_Vue){
    Vue = _Vue;
    
    Vue.mixin({
      beforeCreate(){
        if(this.$options.router){
          //根实例挂载了router
          // 路由初始化
          this.$options.router.init();
        }
        if(this.$root.$options.router){
          this.$router = this.$root.$options.router;
        }
      }
    })

  }

  constructor(options){
    this._options = options;
    this._routeMap = {};
    this._vm = new Vue({
      data: {
        currentPath : '/'
      }
    })
  }

  init(){
    // 解析路由表
    this.getRouteMap();
    // 注册组件
    this.initComponent();
    // 解析第一次的路由
    this.loadRoute();
    // 监听返回的事件,重新装载组件
    this.onBack();
  }

  getRouteMap(){
    this._options.routes.forEach(route=>{
      this._routeMap[route.path] = route;
    })
  }

  initComponent(){
    const self = this;
    Vue.component('router-view', {
      render(h){
        const path = self._vm.currentPath;
        const component = self._routeMap[path] && self._routeMap[path].component;
        return h(component);
      }
    });
    Vue.component('router-link', {
      props: {
        to: String
      },
      render(h){
        return h('a', {
          class: {
            'router-link-exact-active': self._vm.currentPath === this.to
          },
          attrs: {
            href: this.to
          },
          on: {
            // a标签点击事件
            click: (ev)=>{
              // 阻止默认事件
              ev.preventDefault();
              // 修改地址栏
              window.history.pushState({}, '', this.to);
              // 装载组件
              self._vm.currentPath = this.to;
            }
          }
        }, this.$slots.default);
      }
    });
  }


  loadRoute(){
    window.addEventListener('load', ()=>{
      //得到路由的地址
      let path = window.location.pathname;
      // 加载路由对应的组件
      this._vm.currentPath = path;
    })
  }

  onBack(){
    window.addEventListener('popstate', ()=>{
      //得到路由的地址
      let path = window.location.pathname;
      // 加载路由对应的组件
      this._vm.currentPath = path;
    })
  }


  push(path){
    // 修改地址栏
    window.history.pushState({}, '', path);
    // 加载路由对应的组件
    this._vm.currentPath = path;
  }

  back(){
    window.history.back();
  }

  forward(){
    window.history.forward();
  }

  go(n){
    window.history.go(n);
  }

}

ハッシュルーティングの原則

アドレスバーのルーティングスイッチへの変更、onhashchange耳を傾ける必要が
JSのスイッチ・ルーティング、実際にはアドレスバーのハッシュ値を変更します

  1. URL以下のハッシュ値を変更し、それがサーバーにリクエストを送信しません、そのため、ページを毎回ハッシュ値の変更をリフレッシュなhashchangeイベントをトリガするので、私たちは(場所を何が起こったかのハッシュ値を知るために、このイベントを監視することができません。 .hash)
  2. 変更は、ページジャンプハッシュを誘発しない、ハッシュリンクは、現在のページの断片である、ページがない場合は、効果がない、対応する位置にスクロールします

ハッシュ回路図.PNG

コードの実装:
main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  router: router,
  render: h => h(App)
}).$mount('#app')

router.js

import Vue from 'vue'
import VueRouter from './vue-router'
import Home from './views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'home',
    component: Home
  },
  {
    path: '/about',
    name: 'about',
    component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
  }
]

const router = new VueRouter({
  routes
})

export default router

index.js VUE-ルータフォルダ

let Vue = null;

export default class Router{

  static install(_Vue){
    Vue = _Vue;

    Vue.mixin({
      beforeCreate(){
        if(this.$options.router){
          //只有vm实例,而且是配置了router的vm实例,会进来
          this.$options.router.init(); 
        }
        if(this.$root.$options.router){
          this.$router = this.$root.$options.router;
        }
      }
    });

  }


  constructor(options){
    this._options = options;
    
    this._routeMap = {};

    this._routeEach = [];

    this._vm = new Vue({
      data: {
        //保存当前路由所在的地址
        currentPath: '/'
      }
    });

  }

  init(){
    // 解析路由表
    this.getRouteMap();
    
    // 配置组件
    this.initComponent();
    
    // 加载路由
    this.addEvents();
  }

  // 解析路由表
  getRouteMap(){
    this._options.routes.forEach(route=>{
      this._routeMap[route.path] = route;
    });
  }

  initComponent(){
    let self = this; 
    Vue.component('router-view', {
      render(h){
        let currentPath = self._vm.currentPath;
        let component = self._routeMap[currentPath].component;
        return h(component);
      }
    });
    Vue.component('router-link', {
      props: {
        to: String
      },
      render(h){
        return h(
          'a',
          {
            class: {
              'router-link-exact-active': self._vm.currentPath === this.to
            },
            attrs: {
              href: '#'+this.to
            }
          },
          this.$slots.default
        )
      }
    });
  }

  // 加载路由
  addEvents(){
    window.addEventListener('hashchange', this.onHashChange.bind(this));
    window.addEventListener('load', this.onHashChange.bind(this));
  }

  getPath(){
    return window.location.hash.slice(1);
  }


  // 处理路由
  onHashChange(ev){
    console.log('onHashChange函数调用了.....');
    

    //调用路由拦截
    if(this._routeEach.length > 0){
      let {newURL, oldURL} = ev;
      let to = {};
      let from = {};
      if(oldURL){
        // hashChange事件
        // 重新设置currentPath,那么router-view就会重新装载
        to = {
          path: newURL.split('#')[1]
        }
        from = {
          path: oldURL.split('#')[1]
        }
      }else{
        //load事件
        to = {
          path: window.location.hash.split('#')[1]
        }
        from = {
          path: null
        }
      }

      this.runEach(to, from);
      
    }
    //没有拦截
    else{
      let path = this.getPath();
      let route = this._routeMap[path];
      this._vm.currentPath = route.path;
    }
  }

  // 切换路由
  push(path){
    // this._vm.currentPath = path;
    window.location.hash = '#'+path;
  }

  // 路由拦截
  beforeEach(cb){
    this._routeEach.push(cb);
  }

  //执行路由拦截
  runEach(to, from, index = 0){
    console.log(index);
    this._routeEach[index](to, from, ()=>{
      index++;
      if(index < this._routeEach.length){
        this.runEach(to, from, index);
      }else{
        let path = this.getPath();
        let route = this._routeMap[path];
        this._vm.currentPath = route.path;
      }
    });
  }

}

履歴ハッシュルーティングとの違いをルーティングします:

  1. ハッシュ位だけ戻って変更することができ、およびハッシュ値と元の値が異なっている必要があります
  2. pushStateパス、クエリパラメータとフラグメント識別子を変更することができpushStateは、複数のルートの前端に沿ってハッシュアクセス方法よりも、よりエレガントな、しかし履歴モードは、バックエンドが必要
公開された13元の記事 ウォン称賛22 ビュー390

おすすめ

転載: blog.csdn.net/weixin_44691775/article/details/104424612