javascript Backbone.js 路由器和 Internet Explorer 重定向问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12062056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:12:48  来源:igfitidea点击:

Backbone.js router and redirection problems with Internet Explorer

javascriptbackbone.js

提问by Kerry

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).

路由器继续实例化一些集合、视图等。在 Chrome、Safari、Firefox 和 Opera 中一切正常。但不是在 IE 8 或 9(也可能是 10,我还没有测试过)。

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.

在 IE8 或 9 中,当第一次请求页面时,它开始加载,但是一旦文档准备好(因此路由器实例化并启动历史记录),页面就会重定向到站点根目录。

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.

在重定向之前,我在控制台中看不到任何内容。没有任何其他地方的代码可以以某种方式做到这一点 - 我的意思是,我们有一个庞大的代码库,所以它总是有可能的,但是没有任何处理路由或历史 API 的东西可能会发生冲突。

The weird part is if the pushState: trueoption 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...

奇怪的部分是,如果该pushState: true选项被删除,页面不会重定向,它会按原样完全加载 - 路由器不会继续做任何事情,因为它现在期待 hashbang 样式的路由,但至少它不会不要把你踢回网站的根目录。重新添加该选项,它再次中断...

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.

所以,我的第一个想法显然是“嗯……IE8 或 9 不支持历史 API……一定是这样”但是 Backbone.js 应该恢复到那些旧浏览器的 hashbang 样式的 URL,所以不可能那样。

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

在处理 Backbone.js 路由器时,到底是什么导致 IE 重定向回主页?

EDIT

编辑

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

(现在可以忽略下面的内容,因为 EDIT 2 证明它什么也没做,尽管删除尾随逗号是可行的)

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 alertand console.log) and called it just after var router = new App.Routers.ExampleRouter();.

好的,经过一些调试并真正抓住稻草后,我发现路由器实际上并没有被实例化 - 没有调用初始化方法,没有能力在路由器上调用自定义方法(我只是做了一个愚蠢的方法alertconsole.log) 并在 之后调用它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).

调用该方法会返回如下错误:“对象不支持该属性或方法”(所有这些都只是 IE,在其他浏览器中也可以)。但这并不是路由器独有的,我也调用了一个新模型并做了同样的事情,同样的事情......只是没有被“看到”。对象错误的 Google 建议使用尾随逗号。代码库中确实有一些,我删除了所有这些,看起来事情进展顺利。突然之间,路由器(和模型)非常多 - 调用了初始化方法,调用了自定义方法等。我认为逗号可能已经停止了所有正在解析的 JS(我们连接了多个文件)。

I'd obviously been doing all of this with the pushStateoption removed. I then added pushState: trueback 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: trueoption and the page just doesn't load, and kicks you back to the homepage.

我显然已经在pushState删除选项的情况下完成了所有这些操作。然后我又pushState: true真诚地想,如果发生了上述情况,就可以解决问题。我当时想“啊,路由器从来没有真正‘存在过’,所以可能Backbone.History.Start({pushState: true})被调用发送它寻找路由,由于路由器没有被实例化,所以不存在,回到主页的回扣只是一些有点副作用”但唉,不,完全相同的事情仍在发生。添加pushState: true选项,页面不会加载,并将您踢回主页。

EDIT 2

编辑 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:

好的,所以我尝试了一些进一步的事情,但无济于事。我制作了一个完全独立的空白页面,它通过 CDN 引入 jQuery、Backbone.js 和 Underscore.js,并包含一些用于创建路由器、实例化它并调用 Backbone.History.Start() 的准系统 JavaScript。该页面的完整代码是:

<!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.

就是这样,完全准系统,不受任何其他站点资产等的影响。完全相同的事情仍然发生。所有浏览器都按预期执行,除了 IE(在 8 和 9 上测试),它再次开始加载页面,然后执行路由并突然重定向回主页。如果我关闭 pushState 并使用 hashbangs,一切都会按预期工作 - 所以路由在 IE 中对我来说“有效”,只是在 pushState 设置为 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?

我看不出这是前端的东西,因为我已经尽可能地剥离了一切?有没有办法这是与服务器相关的事情?后端是 Ruby on Rails,问题出现在本地和临时/实时服务器上。还是我严重误解了 Backbone.js 使用 IE 将 pushState 降级为 hashbangs 的方式?

EDIT 3

编辑 3

I've uploaded a video of the problem

上传了问题的视频

回答by Thor Larholm

Internet Explorer doesn't support pushState until IE 10, see

Internet Explorer 直到 IE 10 才支持 pushState,请参阅

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

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

Edit:

编辑:

To start History with an optional pushState you could go with this:

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

Backbone.history.start({pushState: "pushState" in window.history});

回答by Bertrand Marron

It looks to me that your application is not being served from the root URL (/).

在我看来,您的应用程序不是从根 URL ( /) 提供的。

You're requesting http://example.com/sub/ietest.html, and Backbone redirects to http://example.com/#sub/ietest.html.

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

You probably want to initialize Backbone.historyspecifying a root URL:

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

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

I haven't really dug into the source code of your page (and the JS is minified), but this seems to be the case. Maybe root: '/bible/'?

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

回答by miro

try to comment all the console.log() calls. In my case that was the problem for ie9. Yes, I'm also asking the question that why :-), very odd

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

(I didn't use pushState, but that should not matter I guess)

(我没有使用 pushState,但我想这应该无关紧要)

回答by hellatan

This has seemed to work for me in terms of getting IE8/9 (we don't support 7 at work) to use the hash correctly:

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

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

I kept the settings object separate as I was having issues with the services I'm using at work and not returning results for whatever reason. Whether or not that results issues is from adding this change is still up for debate. That is also limited to my use case.

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

also to note for IE is that you now need to handle the hashes for deeplinking.

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

I use "silent": trueb/c I'm rendering initial results on page load and this will prevent any calls from happening. from the backbone docs:

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

If the server has already rendered the entire page, and you don't want the initial route to trigger when starting History, pass silent: true.
如果服务器已经渲染了整个页面,并且您不希望在启动 History 时触发初始路由,请传递silent: true。

回答by charliequinn

Not sure if this option was available when question was originally posted...

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

I got round this issue for browsers < IE 10 (no support for pushState) by adding option of {hashChange: false} when calling start, as detailed here - http://backbonejs.org/#History-start.

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

回答by Bjorn

Check this out:

看一下这个:

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

Credits go to http://blog.isotoma.com/2014/01/backbone-history-and-ie9/

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

回答by born2net

this worked for me: Backbone.history.start({root: '/my_app_dir_here/'});

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