12

bit of a weird one and I'm a little baffled...

I have a page, on that page is the following (well, with a few name changes):

$(document).ready(function() {
  var router = new App.Routers.ExampleRouter();
  Backbone.history.start({pushState: true});
})

The router goes on its way to instantiate some collections, views etc. Everything is working absolutely fine in Chrome, Safari, Firefox and Opera. But not in IE 8 or 9 (maybe 10 too, I haven't tested).

In IE8 or 9 when the page is first requested it starts to load, but as soon as the document is ready (and the router therefore instantiated and History started) the page redirects to the site root.

There's nothing in the console that I can see prior to the redirect. There's no code anywhere else that could be somehow doing it - I mean, we have a large codebase, so it's always a possibility, but there's nothing that deals with routing or the History API that could be conflicting.

The weird part is if the pushState: true option is removed, the page doesn't redirect, it loads fully as it should - the router doesn't go on its way to do anything as it's now expecting hashbang style routes, but it at least doesn't kick you back to the site's root. Add the option back in, and it breaks again...

So, my first thought was obviously "Well...the History API isn't supported in IE8 or 9...must be it" but then Backbone.js is supposed to revert back to hashbang style URLs for those older browsers, so it can't be that.

What on earth is causing just IE to redirect back to the homepage when dealing with a Backbone.js router?

EDIT

(The below can probably be ignored now as EDIT 2 proves it did nothing, although yay for removing trailing commas)

Okay, so after a little debugging and really clutching at straws I found that the router wasn't actually being instantiated - no initialize method being called, no ability to call custom methods on the router (I'd just made a silly method to alert and console.log) and called it just after var router = new App.Routers.ExampleRouter();.

Calling the method was returning an error along the lines of: "object doesn't support that property or method" (all of this is just IE again, fine in other browsers). This wasn't unique to the router though, I invoked a new model too and did the same things, same thing...just wasn't being "seen". A Google of the object error suggested trailing-commas. Right enough there were some in the codebase, I removed all of them and it seemed like things were going well. All of a sudden the router (and model) were very much there - initialize method called, custom method called etc. I figured the commas may have stopped all of the JS being parsed (we concatenate multiple files).

I'd obviously been doing all of this with the pushState option removed. I then added pushState: true back in genuinely thinking that would fix it what with the above having happened. I'd thought at the time "Ah, the router never actually 'existed' so maybe Backbone.History.Start({pushState: true}) being called sent it looking for a route, and none existed due to the router not being instantiated, and the kick-back to the homepage was just some sort of side-effect" but alas, no, the exact same thing is still happening. Add in the pushState: true option and the page just doesn't load, and kicks you back to the homepage.

EDIT 2

Okay, so I've tried some further things to no avail. I made a completely separate blank page that pulls in jQuery, Backbone.js and Underscore.js via a CDN and contains some barebones JavaScript for creating a router, instantiating it and calling Backbone.History.Start(). The code in it's entirety for that page is:

<!DOCTYPE html>
<html>
  <head>
    <title>Test IE</title>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery-1.8.0.min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"></script>
    <script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>
    <script>
      $(document).ready(function(){

        App = {
          Routers: {

          }
        };

        App.Routers.RouterTest = Backbone.Router.extend({
          routes: {
            "ietest.html" : "helloWorld"
          },

          initialize: function() {
            console.log("router init");
          },

          helloWorld: function() {
            alert("helloWorld!")
          }
        });
        router = new App.Routers.RouterTest();
        Backbone.history.start({pushState: true});
      });
    </script>

  </head>
  <body>

  </body>
</html>

That's it, completely barebones, no influence from any other site assets etc. The exact same thing still happens. All browsers do what is expected, except IE (tested on 8 and 9) which again starts to load the page, then executes the route and all of a sudden redirected back to the homepage. If I turn pushState off and use hashbangs everything works as expected - so routing does 'work' for me in IE, just not with pushState set to true.

I can't see that this is a front-end thing anymore as I've stripped away everything I can? Is there any way this is a server related thing? The back-end is Ruby on Rails and the problem is exhibited locally and on staging / live servers. Or have I grossly misunderstood the way that Backbone.js degrades pushState to hashbangs with IE?

EDIT 3

I've uploaded a video of the problem

4

7 回答 7

10

Internet Explorer 在 IE 10 之前不支持 pushState,请参阅

http://caniuse.com/#search=pushState

编辑:

要使用可选的 pushState 启动 History,您可以使用以下命令:

Backbone.history.start({pushState: "pushState" in window.history});
于 2012-08-23T11:28:38.367 回答
9

在我看来,您的应用程序没有从根 URL ( /) 提供服务。

您正在请求http://example.com/sub/ietest.html,并且 Backbone 重定向到http://example.com/#sub/ietest.html.

您可能希望初始化Backbone.history指定根 URL:

Backbone.history.start({pushState: true, root: '/sub/'});

我还没有真正深入研究您页面的源代码(并且 JS 被缩小了),但这似乎是这种情况。也许root: '/bible/'

于 2012-08-23T10:08:28.820 回答
4

尝试评论所有 console.log() 调用。就我而言,这就是 ie9 的问题。是的,我也在问为什么:-),很奇怪

(我没有使用 pushState,但我猜这不重要)

于 2012-11-27T23:10:09.417 回答
1

在让 IE8/9(我们不支持 7 在工作中)正确使用哈希方面,这似乎对我有用:

var pushState = !!(window.history && window.history.pushState),
    settings = { pushState: pushState, silent: true, hashChange: !pushState ? true : false };
Backbone.history.start(settings);

我将设置对象分开,因为我在工作中使用的服务存在问题,并且无论出于何种原因都没有返回结果。结果问题是否来自添加此更改仍有待辩论。这也仅限于我的用例。

IE 还需要注意的是,您现在需要处理深度链接的哈希值。

我使用"silent": trueb/c 我在页面加载时呈现初始结果,这将防止发生任何调用。来自主干文档:

如果服务器已经渲染了整个页面,并且您不希望在启动历史记录时触发初始路由,则传递静默:true。
于 2012-12-03T18:51:28.640 回答
0

不确定最初发布问题时此选项是否可用...

我通过在调用 start 时添加 {hashChange: false} 选项解决了浏览器 < IE 10(不支持 pushState)的这个问题,详见此处 - http://backbonejs.org/#History-start

于 2014-05-22T11:00:06.640 回答
0

看一下这个:

if(!(window.history && history.pushState)) {
        Backbone.history.start({ pushState: false, silent: true });
        var fragment = window.location.pathname.substr(
            Backbone.history.options.root.length);
        Backbone.history.navigate(fragment, { trigger: true });
    }
    else {
        Backbone.history.start({ pushState: true });
    }

学分转到http://blog.isotoma.com/2014/01/backbone-history-and-ie9/

于 2014-06-04T13:59:17.627 回答
0

这对我有用:Backbone.history.start({root: '/my_app_dir_here/'});

于 2014-12-02T16:34:17.803 回答