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

Backbone.js router and redirection problems with Internet Explorer

本文关键字:Explorer 重定向 问题 Internet js 路由器 Backbone      更新时间:2023-09-26

有点奇怪,我有点困惑。。。

我有一个页面,该页面上有以下内容(好吧,有一些名称更改):

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

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

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

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

奇怪的是,如果pushState: true选项被删除,页面不会重定向,它会按照应该的方式完全加载——路由器不会像现在预期的hashbang风格的路由那样继续做任何事情,但它至少不会把你踢回网站的根目录。将选项重新添加到中,它将再次中断。。。

因此,我的第一个想法显然是"好吧…IE8或9不支持历史API…必须是这样",但Backbone.js应该恢复到那些旧浏览器的hashbang风格的URL,所以不可能是这样。

究竟是什么原因导致IE在处理Backbone.js路由器时重定向回主页?

编辑

(下面的内容现在可能可以忽略了,因为EDIT 2证明它什么都没做,尽管是用来删除尾部逗号的)

好吧,经过一点调试,我发现路由器实际上并没有被实例化——没有调用初始化方法,也没有能力在路由器上调用自定义方法(我只是对alertconsole.log做了一个愚蠢的方法),并在var router = new App.Routers.ExampleRouter();之后调用了它。

调用该方法返回的错误如下:"对象不支持该属性或方法"(所有这些都只是IE,在其他浏览器中很好)。不过,这并不是路由器独有的,我也调用了一个新模型,做了同样的事情,同样的事情。。。只是没有被"看见"。谷歌上的一个对象错误建议在后面加逗号。没错,代码库中有一些,我把它们都删除了,看起来一切都很顺利。突然之间,路由器(和模型)就在那里了——初始化方法调用,自定义方法调用等等。我认为逗号可能已经停止了所有JS的解析(我们连接了多个文件)。

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

编辑2

好吧,所以我尝试了一些进一步的事情,但没有成功。我制作了一个完全独立的空白页面,通过CDN引入jQuery、Backbone.js和Undercore.js,并包含一些用于创建路由器、实例化路由器和调用Backbone的基本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>

就是这样,完全裸露,没有任何其他网站资产的影响等等。同样的事情仍然会发生。所有浏览器都按预期操作,除了IE(在8和9上测试),它再次开始加载页面,然后执行路由,然后突然重定向回主页。如果我关闭pushState并使用hashbangs,一切都会按预期进行——所以路由在IE中对我来说确实"有效",只是在pushState设置为true的情况下不起作用。

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

编辑3

我上传了一个问题的视频

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

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

编辑:

要使用可选的pushState启动历史记录,您可以使用以下选项:

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

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

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

您可能想要初始化Backbone.history,指定一个根URL:

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

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

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

(我没有使用pushState,但我想这应该没关系)

这似乎对我来说很有效,可以让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": true b/c,我在页面加载时呈现初始结果,这将防止发生任何调用。来自主干文档:

如果服务器已经呈现了整个页面,并且您不希望在启动History时触发初始路由,请传递silent:true。

不确定这个选项在最初发布问题时是否可用。。。

我绕过了浏览器的这个问题<IE 10(不支持pushState)通过在调用start时添加{hashChange:false}选项,详细信息如下-http://backbonejs.org/#History-启动。

检查一下:

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/

这对我来说很有效:Backbone.history.start({root:'/my_app_dir_here/'});