在骨干网中使用查询字符串(1.0.0)

时间:2013-05-13 16:49:51

标签: backbone.js query-string backbone-routing

我有一种情况,我似乎无法弄明白。如果有人知道如何解决这个问题,我很乐意听取建议。谢谢

我有一个“全局视图”,可以在应用程序的子视图栏中看到,这是一个日历,此日历在整个应用程序中用作全局日历,因此几乎所有视图都使用日历视图&模型根据所选日期设置显示数据。

每次更改日期时,此日历视图/模型都应该有一些存储在历史记录中的方法,这个(我认为)是每次更改日期时使用单个URL或查询字符串参数完成的,例如

webapp/view1?date=20120301

当日期改变时,它的查询字符串也是如此。

我想使用查询字符串参数,所以我不必在每个路由上指定(/:date)可选参数。

当查询字符串被更改时,主题是停止触发路由更改或历史事件,它们只是忽略Backbone.History实现上的查询字符串,这打破了我的所有实现,因为我无法每次查询查询字符串已更改,因此“后退”按钮不会触发更改事件,因此我无法更改模型上可更改日历日期的日期。

我知道一个简单的解决方案就是使用“漂亮的URL”并将日期参数添加到每个视图中,但我试图避免这种情况。

有什么建议吗? 提前致谢


更新

我最终使用了像Backbone文档建议的“漂亮的URL”,因为使用查询字符串会给跟踪URL更改和历史记录带来很多麻烦,使用hashchange而不是pushState也会无法正常工作。

所以,我的代码最终是这样的:

将路由器,视图,控制器等内容附加到路由器的“路由”事件中,检查日期的URI并将此日期设置为日历选择器:

this.listenTo(myRouter, "route", this.routeChanged);

然后,这种方法会做类似的事情:

checkURIdateParameter: function (route, arr) {
        var found = false; 
        for (var i = 0; i < arr.length ; i++) {
            if (arr && arr[i] && arr[i].indexOf("date=") != -1) {
                if (app.models.dateControl) {
                    var dateFromParameter = new Date(arr[i].substring("date=".length).replace(/\$/g, ":")); 
                    dateFromParameter = (isNaN(dateFromParameter.getTime())) ? app.models.dateControl.defaults.date : dateFromParameter;
                    app.models.dateControl.set("date", dateFromParameter);
                    found = true; 
                }
            }
        }
        if (!found) app.models.dateControl.set("date", app.models.dateControl.defaults.date, {changeURI:false}); 
    }

这个函数将从URI读取params并在dateControl上反映这些更改。

每次更改日期时,应该有另一种方法负责将URI更新为新的方法(以便params与视图同步),并且可以复制和粘贴链接没问题。

路由器上的某处,视图,控制器:

this.listenTo(app.models.dateControl, "change:date", this.updateURIdateParameter); 

这是一个附加到具有当前日期的模型的方法,此模型由日历选择器(UI控件)或与路径事件链接的方法(routeChanged,上图)进行更新。 / p>

此方法应该执行以下操作:

, updateURIdateParameter: function (a, b, c) {
        if (c && c.changeURI == false) return; //this is in case i don't want to refresh the URI case the default date is set. 

        var currentFragment = Backbone.history.fragment;
        var newFragment = "";
        var dateEncoded = app.models.dateControl.get("date").toJSON().replace(/\:/g, "$");
        newFragment = currentFragment.replace(/\/date=([^/]+)/, "") + "/date=" + dateEncoded; 

        if (newFragment != currentFragment) {
            app.router.navigate(newFragment, false);
        }
    }

此方法获取从相应模型中选择的currentDate,解析它,然后从Backbone.history.fragment中获取URL,对其执行一个很好的正则表达式,它将替换旧的日期参数(如果存在),然后附加新的编码日期。 然后以静默方式导航到此路由,以便不调用检查路由的方法(这可以防止恼人的循环)。

我希望这会有所帮助。

1 个答案:

答案 0 :(得分:0)

我建议使用“Pretty URL”。

在此示例中,浏览器栏中的FYI页面URL将闪烁。

Backbone.Router内的某处:

this.route('*action', function() {
  console.log('404');
});

this.route(/^(.*?)\?date=(\d+)$/, function(route, date) {
  // same current route (with ?date)
  var fragment = Backbone.history.fragment;
  // navigate to main route (to create views etc.)
  this.navigate(route, {trigger:true, replace:true});
  // silent change hash
  this.navigate(fragment);
});

this.route('any', function() {
  // need wait for hash change
  _.defer(function() {
    console.log('parse date here and do what you want', window.location.hash.match(/^(.*?)\?date=(\d+)$/));
  });
});

this.route('route', function() {
  // need wait for hash change
  _.defer(function() {
    console.log('parse date here and do what you want', window.location.hash.match(/^(.*?)\?date=(\d+)$/));
  });
});