zoukankan      html  css  js  c++  java
  • (六)backbone

    Backbone路由本质

    Backbone路由分为两个大块,Router以及History
    用户在Router中定义相关规则,然后开启history.start进行路由监控,执行默认的回调
    所以,Router本身除了定义路由规则,全部调用的是Backbone.history的方法
    Backbone.History的主要关注点事实上是 popstate(hashChange)的回调checkUrl,无论我们触发navigate或者点击浏览器后退
    皆是进入此入口,再回调至Router定义的回调,从而实现相关逻辑

    •创建规则

     1 var App = Backbone.Router.extend({
     2     routes: {
     3       "": "index",    // #index
     4       "index": "index",    // #index
     5       "detail": "detail"    // #detail
     6     },
     7     index: function () {
     8       var index = new Index(this.interface);
     9   
    10    },
    11    detail: function () {
    12      var detail = new Detail(this.interface);
    13  
    14    },
    15    initialize: function () {
    16  
    17    },
    18    interface: {
    19      forward: function (url) {
    20        window.location.href = ('#' + url).replace(/^#+/, '#');
    21      }
    22  
    23    }
    24 });

    •开启路由控制

    Backbone.history.start();

    Backbone.history源码分析

    history构造函数

     1 var History = Backbone.History = function () {
     2   this.handlers = [];
     3   _.bindAll(this, 'checkUrl');
     4 
     5   // Ensure that `History` can be used outside of the browser.
     6   if (typeof window !== 'undefined') {
     7     this.location = window.location;
     8     this.history = window.history;
     9   }
    10 };

    history.start 函数

     1 start: function(options) {
     2       if (History.started) throw new Error("Backbone.history has already been started");
     3       History.started = true;
     4 
     5       // Figure out the initial configuration. Do we need an iframe?
     6       // Is pushState desired ... is it available?
     7       this.options          = _.extend({root: '/'}, this.options, options);
     8       this.root             = this.options.root;
     9       this._wantsHashChange = this.options.hashChange !== false;
    10       this._wantsPushState  = !!this.options.pushState;
    11       this._hasPushState    = !!(this.options.pushState && this.history && this.history.pushState);
    12       var fragment          = this.getFragment();
    13       var docMode           = document.documentMode;
    14       var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
    15 
    16       // Normalize root to always include a leading and trailing slash.
    17       this.root = ('/' + this.root + '/').replace(rootStripper, '/');
    18 
    19       // 老版本ie以及希望使用hashChange, 使用iframe实现
    20       if (oldIE && this._wantsHashChange) {
    21         var frame = Backbone.$('<iframe src="javascript:0" tabindex="-1">');
    22         this.iframe = frame.hide().appendTo('body')[0].contentWindow;
    23         this.navigate(fragment);
    24       }
    25       
    26       // Depending on whether we're using pushState or hashes, and whether
    27       // 'onhashchange' is supported, determine how we check the URL state.
    28       if (this._hasPushState) {
    29         Backbone.$(window).on('popstate', this.checkUrl);
    30       } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
    31         Backbone.$(window).on('hashchange', this.checkUrl);
    32       } else if (this._wantsHashChange) {
    33         this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
    34       }   
    /* 取决于选择hash还是pushState
          如果使用 pushState,调用方法
    Backbone.history.start({ pushState: true });
    */ 35 36 // Determine if we need to change the base url, for a pushState link 37 // opened by a non-pushState browser. 38 this.fragment = fragment; 39 var loc = this.location; 40 41 // Transition from hashChange to pushState or vice versa if both are 42 // requested. 43 if (this._wantsHashChange && this._wantsPushState) { 44 45 // If we've started off with a route from a `pushState`-enabled 46 // browser, but we're currently in a browser that doesn't support it... 47 if (!this._hasPushState && !this.atRoot()) { 48 this.fragment = this.getFragment(null, true); 49 this.location.replace(this.root + '#' + this.fragment); 50 // Return immediately as browser will do redirect to new url 51 return true; 52 53 // Or if we've started out with a hash-based route, but we're currently 54 // in a browser where it could be `pushState`-based instead... 55 } else if (this._hasPushState && this.atRoot() && loc.hash) { 56 this.fragment = this.getHash().replace(routeStripper, ''); 57 this.history.replaceState({}, document.title, this.root + this.fragment); 58 } 59 60 } 61 62 if (!this.options.silent) return this.loadUrl(); 63 }

    统一入口 loadUrl

    loadUrl: function (fragmentOverride) {
      var fragment = this.fragment = this.getFragment(fragmentOverride);
      var matched = _.any(this.handlers, function (handler) {      // handlers是routes定义的集合,实例化Router时导入
        if (handler.route.test(fragment)) {
          handler.callback(fragment);
          return true;
        }
      });
      return matched;
    }
  • 相关阅读:
    Codeforces Round #358 (Div. 2)
    Codeforces Round #357 (Div. 2)
    Codeforces Round #356 (Div. 2)
    第11章例题(紫书)
    第10章例题(紫书)
    Codeforces Round #354 (Div. 2)
    2016百度之星
    BestCoder 1st Anniversary
    BestCoder Round #41
    BestCoder Round #40
  • 原文地址:https://www.cnblogs.com/huair_12/p/4173727.html
Copyright © 2011-2022 走看看