Backbone路由器在Safari和Chrome上使用utf-8字符的工作方式不同

时间:2013-07-09 15:40:25

标签: 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="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>

当用以下内容调用页面时:

file://localhost/whatever.html#charñ

...它会在Safari和Chrome上触发不同的功能。

改变骨干版本对我来说真的不容易。

有没有办法避免这种差异?

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

3 个答案:

答案 0 :(得分:1)

这不应被视为对此的回答使得每个浏览器的工作方式相同但会阻止这种情况发生。据我所知,对于backone将触发的内容没有多少控制权。在Router处理之前,您不能真正过滤网址。

也就是说,您可以为这两种风格创建路线。为了简化这一过程,您可以创建一个特殊对象,该对象将获取utf8字符串并创建路径的urlencoded版本。两条路线都有相同的回调。

另一种可能性是避免url中的utf-8符号并向backbonejs报告错误。使用urlencoded / urldecoded创建两个路由将使该站点可能适用于支持javascript的每个浏览器。缺点是你必须创建n*2路线。

答案 1 :(得分:0)

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

decodeURIComponent('char%C3%B1')

/*
charñ
*/
decodeURIComponent('charñ')

/*
charñ
*/

http://backbonejs.org/docs/backbone.html#section-156之前,您可以在执行正则表达式之前将_extractParameters替换为在decodeURI上调用decodeURIComponentfragment的版本。

尝试的另一种可能性,因为我刚注意到路由可以是正则表达式(参见http://backbonejs.org/docs/backbone.html#section-152):如果你没有很多,你可以使用类似/char(ñ|%C3%B1)/g的东西,或者写为未编码的值生成这样的正则表达式的函数,这样makeRegex('charñ')将生成/char(ñ|%C3%B1)/g,或者正则表达式将生成的任何函数。

答案 2 :(得分:0)

我通过在_bindRoutes中的while循环中添加一行来解决它,以便绑定编码的路径:

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