0

我正在构建一个带有搜索表单和一些结果的简单 Backbone 应用程序。我想:

  • 允许用户更改“order by”选择字段的值,并适当地更新 URL 和结果
  • 确保当用户通过预设 URL 到达时,显示正确的结果,并且所选表单元素与 URL 和结果匹配。

我想我已经找到了正确的控制流程来使用,但我真的很想找人检查一下。基本上,我让我的视图直接更新 URL,然后路由器完成更新模型的工作。然后其他视图听模型。

好像还可以,但是我得在View中手动构造URL,在Router中再解析一遍,感觉是重复的。所以很高兴知道这是否是在 Backbone 中做事的正确方法,或者我是否可以做得更好。

这是伪代码:

 User changes value of select to "price-asc"    
           |                                        
           |                                        
           v                                        
 Form view hears change event, and              
 updates the URL to #order-by-price-asc            
           |                                       
           |                                       
           v                                       
 Router looks at new route,        <----- User loads page, with 
  sets model value                       #order-by-price-asc route
           |
           |
           v   
  Results view hears change 
  to model value, loads in 
  new results via Ajax

这是代码:

HTML:

<select id="order">
    <option value=''></option>
    <option value='price-asc'>price (low to high)</option>
    <option value='price-desc'>price (high to low)</option>
</select>
<div id="results"></div>

JS:

var SearchModel = Backbone.Model.extend({
    initialize: function() {
        this.bind("change:query", function() {
        this.performSearch();
        });
    },
    performSearch: function() {
        // Will eventually do Ajax search here, 
        // but for the moment, just bind to query. 
        this.set("results", this.get("query"));
    },
});

var SearchFormView = Backbone.View.extend({
    el: $('#order'),
    events: {
        "change": "updateURL"
    },
    initialize: function() {
        this.model.on("change:results", this.updateFormClasses, this);
    },
    updateFormClasses: function(model, query) {
        this.$el.val(query);
    },
    updateURL: function(e) {
        var url = '';
        ($('#order').val() !== '') ? url += "/by-" + $('#order').val() : null;
        SearchApp.navigate(url, {trigger: true});
    }
});

var SearchResultsView = Backbone.View.extend({
    el: "#results",
    initialize: function() {
        this.model.on("change:results", this.displayResults, this);
    },
    displayResults: function(model, query) {
        this.$el.text(query)
    }
});

var AppRouter = Backbone.Router.extend({
    routes: {
    "*str": "index",
    },
    initialize: function() {
        this.searchModel = new SearchModel();
        this.searchFormView = new SearchFormView({
            model: this.searchModel
        });
        this.searchResultsView = new SearchResultsView({
            model: this.searchModel
        });
    },
    index: function(str) {
        var ordering = str.match(/by-.*/gi);
        if (ordering !== null) {
            this.searchModel.set({"query": ordering[0].replace('by-','')});
        }
    }
});
var SearchApp = new AppRouter();
Backbone.history.start({});
4

1 回答 1

1

您可以做的优化很少:

  1. 使用可选的路由参数而不是手动解析 url:

    var AppRouter = Backbone.Router.extend({
        routes: {
          "*str(/by-:sort)": "index",
        },
        index: function(str, sort) {
          if(sort) {
            //...
          }
        }
    });
    
  2. 考虑允许视图处理模型更改,而不是通过路由器。为了避免代码重复,将此逻辑封装在模型方法中。

    var SearchModel = Backbone.Model.extend({
      sort: function(field) {
        this.set({query:field});
      }
    });
    
    var SearchFormView = Backbone.View.extend({
      el:"#order",
      events: {
        "change": "updateSort"
      },
      updateSort: function(e) {
        var sortOrder = this.$el.val();
    
        //update model
        this.model.sort(sortOrder);
    
        //navigate without trigger:true, will update the URL but not trigger route
        SearchApp.navigate(sortOrder ? "/by-" + sortOrder : "");
      }
    }    
    
    var AppRouter = Backbone.Router.extend({
        index: function(str, sort) {
          if(sort) {
            this.searchModel.sort(sort);
          }
        }
    }); 
    

另请注意,我将view.el声明更改为, 并使用而不是 jQuery 选择器来#order引用元素。this.$el这些是不相关的,但仍然是最佳实践。

于 2013-02-07T14:06:41.110 回答