【问题标题】:Using query strings in backbone (1.0.0)在主干中使用查询字符串 (1.0.0)
【发布时间】:2013-05-13 16:49:50
【问题描述】:

我这里有一种情况,我似乎无法弄清楚。请如果有人知道如何解决这个问题,我很想听听建议。谢谢

我有一个在应用程序的子导航栏上可见的“全局视图”,即日历,此日历在整个应用程序中充当全局日历,因此几乎所有视图都使用日历视图和模型来设置显示根据所选日期的数据。

每次更改日期时,此日历视图/模型都应该有某种方式存储在历史记录中,这(我认为)是在每次更改日期时使用单个 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 读取参数并将这些更改反映在 dateControl 上的函数。

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

在您的路由器、视图、控制器上的某处:

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

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

这个方法应该做这样的事情:

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

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

我希望这会有所帮助。

【问题讨论】:

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


    【解决方案1】:

    我建议使用“Pretty URL”。

    浏览器栏中的仅供参考的页面 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+)$/));
      });
    });
    

    【讨论】:

    • 谢谢,最后我使用了“漂亮的 URL”,查询字符串的使用让我很头疼。我使用正则表达式根据所选日期更改 URL。感谢您的时间和回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多