Prevent navigating to another view if contents are unsaved

前端 未结 6 1605
无人共我
无人共我 2021-02-05 20:24

We have a backbone.js app that displays a number of forms to the user. What we want is very simple: if the user goes to another page without saving the filled-in form, we want t

6条回答
  •  情书的邮戳
    2021-02-05 20:43

    I would also hack Backbone.history.loadUrl, that's where loading the route callbacks happen.

    // ALLOW PREVENTING HASH NAVIGATION
    
    var originalFn = Backbone.history.loadUrl;
    
    Backbone.history.loadUrl = function() {
        // I introduced an application state variable, but it can be solved in multiple ways
        if (app && app.states.isNavigationBlocked) {
            var previousFragment = Backbone.history.fragment;
            window.location.hash = '#' + previousFragment;
            return false;
        }
        else {
            return originalFn.apply(this, arguments);
        }
    };
    

    Explanation:

    1)

    Backbone listens to the hashchange event and sets Backbone.history.checkUrl as a callback: https://github.com/jashkenas/backbone/blob/1.1.2/backbone.js#L1414

    Backbone.$(window).on('hashchange', this.checkUrl);
    

    2)

    Backbone.history.checkUrl checks if the hash has changed and calls Backbone.history.loadUrl

    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();
    },
    

    3)

    Backbone.history.loadUrl finds the first matching route and calls its callback:

    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;
        }
      });
    },
    

    Useful note:

    Backbone.history.fragment stores the current hash, it's set in Backbone.history.loadUrl, so we can access it AFTER the hashchange event but BEFORE the router callbacks do their job.

提交回复
热议问题