How to refresh a page in a backbone application

2019-03-08 11:25发布

问题:

I am using backbone to build my web app.

Currently I am facing an issue whereby if I am on the home page, I am unable to refresh the same page by just clicking on the 'home' button again.

I believe that this is the limitation provided by backbone (does not reload the page if the same URL is called)

Is there any way around this? So that I can trigger a page reload when I click on the home button again i.e. call the same URL again?

回答1:

Looking at the backbone.js source, it seems as though this is not possible by default, since it only responds to a url change. And since clicking the same link, you would not trigger a change event.

Code in Backbone.History:

$(window).bind('hashchange', this.checkUrl);

You'll need to handle a non-change yourself. Here's what I did:

$('.nav-links').click(function(e) {
    var newFragment = Backbone.history.getFragment($(this).attr('href'));
    if (Backbone.history.fragment == newFragment) {
        // need to null out Backbone.history.fragement because 
        // navigate method will ignore when it is the same as newFragment
        Backbone.history.fragment = null;
        Backbone.history.navigate(newFragment, true);
    }
});


回答2:

You're looking for Backbone.history.loadUrl. From the Annotated Source:

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.

So, for a simple refresh link, you can add the following event to your Backbone.View:

events: {
  'click a#refresh': function() {
    Backbone.history.loadUrl();
    return false;
  }
}


回答3:

In case you want to reload the whole page with a desired view. This might make senes for the home button. The advantage will be that it'll refresh the memory.

Go to any route without loading it (without the 'true') and then reload

Backbone.history.navigate('route/goes/here');
window.location.reload();


回答4:

The backbone.history.loadUrl is the solution.

The click handling function of your Home button (if the home is the root / of your WebApp) should be:

myAppRouter.navigate('');
Backbone.history.loadUrl();


回答5:

I needed to 'refresh' my page on orientation change event because not all of my css media queries for portrait mode where executed correctly by default. This is what I ended up doing:

Backbone.history.fragment = null;
Backbone.history.navigate(document.location.hash, true); 

Of course, for the completeness of this answer, this was wrapped in some orientation change handling code:

window.addEventListener('orientationchange', function () {
    Backbone.history.fragment = null;
    Backbone.history.navigate(document.location.hash, true); 
}, false);


回答6:

You could also just make a meaningless change to the url by adding a random number to the end:

var url = $(this).attr('href') + '?rand=' + Math.floor(Math.random() * 1000);
Backbone.history.navigate(url, true);

This is especially useful for IE since it will not request new data via an AJAX call if the url has not changed.



回答7:

You can easily refresh the page using below approach:

@win_loc = window.location.toString().replace("#","")
Backbone.history.redirectTo(@win_loc)


回答8:

This is not upto backbone. The same works fine in chrome(webkit browsers), but not in firefox. Its a browser behavior



回答9:

The difference between http://localhost.com/ and http://localhost.com/#!/ is that the second is a link to anchor, it does not load a page, it only looks for the anchor in the current page, and scrolls to it if found. You need to make your link looks like the first one, no "#" close to end.



回答10:

You can often modify your route to include a splat, so that you can append a random string to the end of an href to make it unique, but still match the "home" route. (Note: make this your last route.)

In the routes:

routes: {
    "*str": "home"
}

In the view:

render: function() {
    var data = {href: +(new Date())};
    _.extend(data, this.model.attributes);
    this.$el.html(this.template(data));
    return this;
}

In the template (handlebars shown here):

<a href="{{href}}">Home Link</a>


回答11:

In order to provide a reusable snippet of code I augmented the Backbone.View with a helper method to reuse it wherever we need to reload the same page despite the Backbone router limitations.

In our app.js file or any other proper place

Backbone.View = Backbone.View.extend({
    refreshPage: function(e){
        if(e.target.pathname){
            Backbone.history.navigate(e.target.pathname);
        }
        window.location.reload();           
    }
});

This way if we have a link such as

<a href="/whatever" id="whateverId">Some text </a>

In our View we would just need to bind the click event to that callback to leverage the refresh page feature, as far as the refreshPage helper will be available through the prototype chain

events: {
    'click #whateverId': 'refreshPage', 
}

As far as we don't need to change the "a tag" it's a cleaner solution that will save some boilerplate coding

Hope it helps



回答12:

It works with

 myBackboneRouter.navigate("users", {trigger: true})


回答13:

Here's my favorite approach so far:

 if (!Backbone.history.navigate(urlPath, true)) {
      Backbone.history.loadUrl();
 }