Backbone.js 主干路由器在Safari和Chrome上以不同的方式使用utf-8字符

Backbone.js 主干路由器在Safari和Chrome上以不同的方式使用utf-8字符,backbone.js,utf-8,Backbone.js,Utf 8,我有一个例子,使用带有utf-8非ascii字符的路由: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Backbone Test</title> </head> <body> <script src

我有一个例子,使用带有utf-8非ascii字符的路由:

<!DOCTYPE html>
 <html>
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Backbone Test</title>
 </head>
 <body>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
   <script src="http://ajax.cdnjs.com/ajax/libs/underscore.js/1.3.1/underscore-min.js"></script>
   <script src="http://ajax.cdnjs.com/ajax/libs/backbone.js/0.9.2/backbone-min.js"></script>

   <script>

        (function(){

        window.App = {
            Models: {},
            Collections: {},
            Views: {},
            Router: {}
        };

        })();

        App.Router = Backbone.Router.extend({
            routes: {
                'charñ': 'charChrome',
                'char%C3%B1': 'charSafari'
            },

            charChrome: function(){
                $(document.body).append("Chrome-compatible route triggered.<br/>");
            },

            charSafari: function(){
                $(document.body).append("Safari-compatible route triggered.<br/>");
            },

        });

        new App.Router;
        Backbone.history.start();

   </script>

   <h1>HELLO THERE</h1>
 </body>
 </html>
…它在Safari和Chrome上触发不同的功能

对我来说,更改主干版本真的不容易

有没有办法避免这种差异


注意:有趣的是,删除meta标记会破坏Chrome路由。

当URL传递给函数时,您是否尝试过对其进行解码?可能是Chrome为您解码URL,而Safari则没有
'char%C3%B1'
在使用URI解码器时将解码为
'charñ'
很好,并且它应该对已经解码的字符串没有影响(当然,假设使用的编码是正确的)

解码组件('char%C3%B1') /* 沙尔尼 */ 解码组件('charñ') /* 沙尔尼 */ 现在,您可以在执行正则表达式之前,使用调用
decodeURI
decodeURIComponent
的版本替换
\u extractParameters


另一种尝试的可能性是,正如我刚才注意到的,路由可以是正则表达式(请参阅):如果没有很多路由,可以使用类似于
/char(ñ|%C3%B1)/g
,或者编写一个函数为未编码的值生成这样的正则表达式,这样
makeRegex('charñ')
将生成
/char(ñ|%C3%B1)/g
,或任何正则表达式。

这不应该被视为是一个答案,它使每个浏览器的工作原理相同,但防止这种情况发生。据我所知,没有太多控制backone将触发什么。这不像你真的可以在url被
路由器处理之前对其进行过滤

也就是说,您可以为这两种样式创建路由。为了简化此操作,您可以创建一个特殊的对象,该对象将获得utf8字符串并创建路由的URL编码版本。两个路由将具有相同的回调


另一种可能是在url中避免使用utf-8符号,并向backbonejs报告错误。使用urlencoded/urldecoded创建这两个路由将使站点在可能所有支持javascript的浏览器中都能正常工作。缺点是您必须创建
n*2
路由。

我通过在whil中添加一行来解决这个问题e循环,在_bindRoutes内,也用于绑定编码的路由:

_bindRoutes: function() {
  if (!this.routes) return;
  this.routes = _.result(this, 'routes');
  var route, routes = _.keys(this.routes);
  while ((route = routes.pop()) != null) {
    this.route(route, this.routes[route]);
    //add this line:
    this.route(encodeURIComponent(route).replace(/%2F/g,'/').replace(/%3A/g,':'), this.routes[route]);
  }
}

Safari和Firefox或Safari和Chrome?问题的标题与问题不匹配我认为这不会有什么区别,但您是否尝试过在使用HTML5 doctype时指定编码的HTML5方法?(
)@LoïcFaure Lacroix:对不起,Chrome。我已经修复了它。@jab:是的,它不能解决问题,唉。@St0rM我会尝试在Firefox/Opera或其他浏览器上检查在其他浏览器上使用了哪种行为。@St0rM经过,只有在将URI片段与路由匹配后,才会对值进行解码。
_bindRoutes: function() {
  if (!this.routes) return;
  this.routes = _.result(this, 'routes');
  var route, routes = _.keys(this.routes);
  while ((route = routes.pop()) != null) {
    this.route(route, this.routes[route]);
    //add this line:
    this.route(encodeURIComponent(route).replace(/%2F/g,'/').replace(/%3A/g,':'), this.routes[route]);
  }
}