博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
backbone 学习之history
阅读量:6701 次
发布时间:2019-06-25

本文共 9669 字,大约阅读时间需要 32 分钟。

Backbone中的历史管理对象,包含兼容性的处理hash方式更改地址或者是popstate式的更改地址方案。直接看源码:

// Backbone.History  // ----------------  // Handles cross-browser history management, based on either  // [pushState](http://diveintohtml5.info/history.html) and real URLs, or  // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)  // and URL fragments. If the browser supports neither (old IE, natch),  // falls back to polling.  var History = Backbone.History = function() {    this.handlers = [];    _.bindAll(this, 'checkUrl');    // Ensure that `History` can be used outside of the browser.    if (typeof window !== 'undefined') {      this.location = window.location;      this.history = window.history;    }  };  // Cached regex for stripping a leading hash/slash and trailing space.  var routeStripper = /^[#\/]|\s+$/g;  // Cached regex for stripping leading and trailing slashes.  var rootStripper = /^\/+|\/+$/g;  // Cached regex for detecting MSIE.  var isExplorer = /msie [\w.]+/;  // Cached regex for removing a trailing slash.  var trailingSlash = /\/$/;  // Has the history handling already been started?  History.started = false;  // Set up all inheritable **Backbone.History** properties and methods.  _.extend(History.prototype, Events, {    // The default interval to poll for hash changes, if necessary, is    // twenty times a second.    // hash更改的事件间隔 针对旧式浏览器    interval: 50,    // Gets the true hash value. Cannot use location.hash directly due to bug    // in Firefox where location.hash will always be decoded.    // firefox取hash的bug    getHash: function(window) {      var match = (window || this).location.href.match(/#(.*)$/);      return match ? match[1] : '';    },    // Get the cross-browser normalized URL fragment, either from the URL,    // the hash, or the override.    // 跨浏览器的得到URL片段 不管是URL hash 或其他    getFragment: function(fragment, forcePushState) {      if (fragment == null) {        if (this._hasPushState || !this._wantsHashChange || forcePushState) {          fragment = this.location.pathname;          var root = this.root.replace(trailingSlash, '');          if (!fragment.indexOf(root)) fragment = fragment.substr(root.length);        } else {          fragment = this.getHash();        }      }      return fragment.replace(routeStripper, '');    },    // Start the hash change handling, returning `true` if the current URL matches    // an existing route, and `false` otherwise.    // 开始监听hash change事件(兼容性)    start: function(options) {      if (History.started) throw new Error("Backbone.history has already been started");      History.started = true;      // Figure out the initial configuration. Do we need an iframe?      // Is pushState desired ... is it available?      this.options          = _.extend({}, {root: '/'}, this.options, options);      this.root             = this.options.root;      this._wantsHashChange = this.options.hashChange !== false;      this._wantsPushState  = !!this.options.pushState;// 是否采用popstate修改地址栏地址      this._hasPushState    = !!(this.options.pushState && this.history && this.history.pushState);// 支持popstate      var fragment          = this.getFragment();      var docMode           = document.documentMode;      // 老版本ie      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));      // Normalize root to always include a leading and trailing slash.      this.root = ('/' + this.root + '/').replace(rootStripper, '/');      // 老版本ie的兼容性方案      // 利用iframe来做      if (oldIE && this._wantsHashChange) {        this.iframe = Backbone.$('').hide().appendTo('body')[0].contentWindow;        this.navigate(fragment);      }      // Depending on whether we're using pushState or hashes, and whether      // 'onhashchange' is supported, determine how we check the URL state.      // 支持popstate 就监听popstate      // 支持hashchange 就监听hashchange      // 否则的话只能每隔一段时间进行检测了      if (this._hasPushState) {        Backbone.$(window).on('popstate', this.checkUrl);      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {        Backbone.$(window).on('hashchange', this.checkUrl);      } else if (this._wantsHashChange) {        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);      }      // Determine if we need to change the base url, for a pushState link      // opened by a non-pushState browser.      this.fragment = fragment;      var loc = this.location;      var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;      // If we've started off with a route from a `pushState`-enabled browser,      // but we're currently in a browser that doesn't support it...      // 兼容性处理 参数设置与当前浏览器支持情况冲突的时候      if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {        this.fragment = this.getFragment(null, true);        this.location.replace(this.root + this.location.search + '#' + this.fragment);        // Return immediately as browser will do redirect to new url        return true;      // Or if we've started out with a hash-based route, but we're currently      // in a browser where it could be `pushState`-based instead...      } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {        this.fragment = this.getHash().replace(routeStripper, '');        this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);      }      if (!this.options.silent) return this.loadUrl();    },    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,    // but possibly useful for unit testing Routers.    // 停止历史支持    stop: function() {      Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);      clearInterval(this._checkUrlInterval);      History.started = false;    },    // Add a route to be tested when the fragment changes. Routes added later    // may override previous routes.    // 导航到相应的route地址    // 这里用handlers队列处理, 防止快速的改变地址但是没处理完成 引起的问题    route: function(route, callback) {      this.handlers.unshift({route: route, callback: callback});    },    // Checks the current URL to see if it has changed, and if it has,    // calls `loadUrl`, normalizing across the hidden iframe.    // 检查url 兼容性处理    checkUrl: function(e) {      var current = this.getFragment();      if (current === this.fragment && this.iframe) {        current = this.getFragment(this.getHash(this.iframe));      }      if (current === this.fragment) return false;      if (this.iframe) this.navigate(current);      this.loadUrl() || this.loadUrl(this.getHash());    },    // Attempt to load the current URL fragment. If a route succeeds with a    // match, returns `true`. If no defined routes matches the fragment,    // returns `false`.    // load当前的URL片段 如果真的有相应的route地址处理函数 则执行它    loadUrl: function(fragmentOverride) {      var fragment = this.fragment = this.getFragment(fragmentOverride);      var matched = _.any(this.handlers, function(handler) {        if (handler.route.test(fragment)) {          handler.callback(fragment);          return true;        }      });      return matched;    },    // Save a fragment into the hash history, or replace the URL state if the    // 'replace' option is passed. You are responsible for properly URL-encoding    // the fragment in advance.    //    // The options object can contain `trigger: true` if you wish to have the    // route callback be fired (not usually desirable), or `replace: true`, if    // you wish to modify the current URL without adding an entry to the history.    // 导航 根据url片段导航去相应的画面 兼容性处理    navigate: function(fragment, options) {      if (!History.started) return false;      if (!options || options === true) options = {trigger: options};      fragment = this.getFragment(fragment || '');      if (this.fragment === fragment) return;      this.fragment = fragment;      var url = this.root + fragment;      // If pushState is available, we use it to set the fragment as a real URL.      if (this._hasPushState) {        this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);      // If hash changes haven't been explicitly disabled, update the hash      // fragment to store history.      } else if (this._wantsHashChange) {        this._updateHash(this.location, fragment, options.replace);        if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) {          // Opening and closing the iframe tricks IE7 and earlier to push a          // history entry on hash-tag change.  When replace is true, we don't          // want this.          if(!options.replace) this.iframe.document.open().close();          this._updateHash(this.iframe.location, fragment, options.replace);        }      // If you've told us that you explicitly don't want fallback hashchange-      // based history, then `navigate` becomes a page refresh.      } else {        return this.location.assign(url);      }      if (options.trigger) this.loadUrl(fragment);    },    // Update the hash location, either replacing the current entry, or adding    // a new one to the browser history.    // 更新hash值 包含替换当前hash 或者是增加历史到浏览器的历史记录中    _updateHash: function(location, fragment, replace) {      if (replace) {        var href = location.href.replace(/(javascript:|#).*$/, '');        location.replace(href + '#' + fragment);      } else {        // Some browsers require that `hash` contains a leading #.        location.hash = '#' + fragment;      }    }  });  // Create the default Backbone.history.  // 创建默认Backbone history对象  Backbone.history = new History;

 

欢迎指导、纠错、建议。

转载于:https://www.cnblogs.com/xiaobudiandian/archive/2013/03/21/Backbone_history.html

你可能感兴趣的文章
java 消息摘要算法MD
查看>>
Web Service security UserNameToken 使用
查看>>
I/O重定向
查看>>
去除vue项目中的#及其ie9兼容性
查看>>
linux实例 批量修改图片文件名
查看>>
day15(mysql 的多表查询,事务)
查看>>
IOS
查看>>
beta冲刺第三天
查看>>
beta第二天
查看>>
工作中常用的但是又容易忽略的问题
查看>>
css特殊情况
查看>>
洛谷 P2735 电网 Electric Fences Label:计算几何--皮克定理
查看>>
Vue + webpack 项目配置化、接口请求统一管理
查看>>
关于电脑的基础单词笔记
查看>>
安卓App设计博文
查看>>
11.8 开课二个月零四天 (Jquery)
查看>>
ZEN CART 在LINUX系统下设置邮箱方法---用GMAIL设置,方法选择SMTPAUTH
查看>>
ofstream的使用方法--超级精细。C++文件写入、读出函数(转)
查看>>
DOM剪切板
查看>>
10.高效分布
查看>>