首页 > 网站 > WEB开发 > 正文

backbone.Router History源码笔记

2024-04-27 14:20:26
字体:
来源:转载
供稿:网友

backbone.Router History源码笔记

Backbone.History和Backbone.Router

history和router都是控制路由的,做一个单页应用,要控制前进后退,就可以用到他们了。

History类用于监听URL的变化,和触发Action方法,他可以添加对url的监听,

Router类用于定义和解析路由规则,并将URL映射到Action。

router和history一些个人的注解

<!DOCTYPE html><html><head>    <meta charset="utf-8"/>    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />    <title>backbone</title>    <style type="text/CSS">        *{padding:0;margin:0;}        .wrap{width:960px; margin: 100px auto; padding: 20px 0;}        ul{ list-style: none;}    </style></head><body>    <div class="wrap">        <div id="a1"></div>        <div id="a2"></div>        <div id="a3"></div>    </div><script src="http://files.cnblogs.com/wtcsy/jquery.js"></script> <script src="http://files.cnblogs.com/wtcsy/underscore.js"></script><script src="http://files.cnblogs.com/wtcsy/events.js"></script><script>(function(){  // Backbone.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 stripping urls of hash.    var pathStripper = /#.*$/;    // 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;        }    };    // Has the history handling already been started?    History.started = false;        _.extend(History.PRototype, Backbone.Events, {        // The default interval to poll for hash changes, if necessary, is        // twenty times a second.        interval: 50,        // Are we at the app root?        atRoot: function() {            var path = this.location.pathname.replace(/[^//]$/, '$&/');            return path === this.root && !this.location.search;        },        // Gets the true hash value. Cannot use location.hash directly due to bug        // in Firefox where location.hash will always be decoded.        getHash: function(window) {            var match = (window || this).location.href.match(/#(.*)$/);            return match ? match[1] : '';        },        // Get the pathname and search params, without the root.        getPath: function() {            var path = decodeURI(this.location.pathname + this.location.search);            var root = this.root.slice(0, -1);            if (!path.indexOf(root)) path = path.slice(root.length);            return path.slice(1);        },        // Get the cross-browser normalized URL fragment from the path or hash.        getFragment: function(fragment) {            if (fragment == null) {                if (this._haspushState || !this._wantsHashChange) {                    fragment = this.getPath();                } else {                    fragment = this.getHash();                }            }            //var routeStripper = /^[#//]|/s+$/g;            return fragment.replace(routeStripper, '');        },        // Start the hash change handling, returning `true` if the current URL matches        // an existing route, and `false` otherwise.        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._hasHashChange   = 'onhashchange' in window;            this._wantsPushState  = !!this.options.pushState;            this._hasPushState    = !!(this.options.pushState && this.history && this.history.pushState);            this.fragment         = this.getFragment();            // Add a cross-platform `addEventListener` shim for older browsers.            var addEventListener = window.addEventListener || function (eventName, listener) {                return attachEvent('on' + eventName, listener);            };            // Normalize root to always include a leading and trailing slash.            // var routeStripper = /^[#//]|/s+$/g;            this.root = ('/' + this.root + '/').replace(rootStripper, '/');            // Proxy an iframe to handle location events if the browser doesn't            // support the `hashchange` event, HTML5 history, or the user wants            // `hashChange` but not `pushState`.            if (!this._hasHashChange && this._wantsHashChange && (!this._wantsPushState || !this._hasPushState)) {                var iframe = document.createElement('iframe');                iframe.src = 'javascript:0';                iframe.style.display = 'none';                iframe.tabIndex = -1;                var body = document.body;                // Using `appendChild` will throw on IE < 9 if the document is not ready.                this.iframe = body.insertBefore(iframe, body.firstChild).contentWindow;                this.navigate(this.fragment);            }            // Depending on whether we're using pushState or hashes, and whether            // 'onhashchange' is supported, determine how we check the URL state.            if (this._hasPushState) {                addEventListener('popstate', this.checkUrl, false);            } else if (this._wantsHashChange && this._hasHashChange && !this.iframe) {                addEventListener('hashchange', this.checkUrl, false);            } else if (this._wantsHashChange) {                this._checkUrlInterval = setInterval(this.checkUrl, this.interval);            }                    },        // Add a route to be tested when the fragment changes. Routes added later        // may override previous routes.        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.        checkUrl: function(e) {            var current = this.getFragment();            if (current === this.fragment && this.iframe) {                current = this.getHash(this.iframe);            }            if (current === this.fragment) return false;            if (this.iframe) this.navigate(current);            this.loadUrl();        },                // 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`.        loadUrl: function(fragment) {            fragment = this.fragment = this.getFragment(fragment);            return _.any(this.handlers, function(handler) {                if (handler.route.test(fragment)) {                    handler.callback(fragment);                    return true;                }            });        },        // Save a fragment into the has
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表