【问题标题】:Backbone Marionette Slow Composite Views (200+ collections)Backbone Marionette 慢速合成视图(200 多个集合)
【发布时间】:2014-12-09 05:07:52
【问题描述】:

当显示一个包含大约 200 个国家/地区的下拉复合视图集合时,我的应用程序变得太慢了。

在木偶复合视图中处理大型集合时提高性能的最佳方法是什么?

这是控制器中加载速度非常慢的函数。只删除以下几行就很快:

 @layout.shippingCountryRegion.show shippingCountryView
 @layout.billingCountryRegion.show billingCountryView

所以这似乎是一个非常缓慢的渲染问题。

 Show.Controller =
  showProfile: ->
    @layout = @getLayoutView()

    @layout.on "show", =>
      headerView = @getHeaderView()
      @layout.headerRegion.show headerView

      accessView = @getAccessView()
      @layout.accessRegion.show accessView

      billingReadmeView = @getBillingReadmeView()
      @layout.billingReadmeRegion.show billingReadmeView

      billingFieldsView = @getBillingFieldsView()
      @layout.billingFieldRegion.show billingFieldsView

      shippingReadmeView = @getShippingReadmeView()
      @layout.shippingReadmeRegion.show shippingReadmeView

      shippingFieldsView = @getShippingFieldsView()
      @layout.shippingFieldRegion.show shippingFieldsView

      MyApp.request "location:get_countries", (countries) =>
        billingCountryView = @getBillingCountryView(countries)
        @layout.billingCountryRegion.show billingCountryView

      MyApp.request "location:get_states", MyApp.activeCustomer.get('billing_country_id'), (states) =>
        billingStateView = @getBillingStatesView(states)
        @layout.billingStateRegion.show billingStateView

      MyApp.request "location:get_countries", (countries) =>
        shippingCountryView = @getShippingCountryView(countries)
         @layout.shippingCountryRegion.show shippingCountryView

      MyApp.request "location:get_states", MyApp.activeCustomer.get('shipping_country_id'), (states) =>
        shippingStateView = @getShippingStatesView(states)
        @layout.shippingStateRegion.show shippingStateView

    MyApp.mainRegion.show @layout

计费国家/地区视图:

class View.BillingCountryDropdownItem extends MyApp.Views.ItemView
  template: billingCountryItemTpl
  tagName: "option"

  onRender: ->
    this.$el.attr('value', this.model.get('id'));
    if MyApp.activeCustomer.get('billing_country_id') == this.model.get('id')
      this.$el.attr('selected', 'selected');

class View.BillingCountryDropdown extends MyApp.Views.CompositeView
  template: billingCountryTpl
  itemView: View.BillingCountryDropdownItem
  itemViewContainer: "select"

模板,简单地说:

        <label>Country
        <select id="billing_country_id" name="billing_country_id">
           <%- name %>
        </select>
    </label>

【问题讨论】:

  • 你为什么用onRender方法设置模型的值?
  • 复合模板中的 是什么?

标签: backbone.js collections marionette


【解决方案1】:

您的代码可以优化。只需将onRender 方法的内容移动到ItemView 属性即可。

class View.BillingCountryDropdownItem extends MyApp.Views.ItemView
  template: billingCountryItemTpl
  tagName: "option"

  attributes: -> 
    var id = this.model.get('id'); 
    var attributes = { 'value': id };
    if MyApp.activeCustomer.get('billing_country_id') == this.model.get('id')
      attributes['selected'] =  'selected';
    return attributes 

这个方法和onRender的区别在于,on render会在collection已经渲染的时候执行,并且会对DOM节点进行200+操作,会带来性能问题。

如果是attributes 方法,它会在视图创建时执行。

【讨论】:

    【解决方案2】:

    您可以遵循一些建议:

    1) 问问你自己,你真的需要一次渲染所有项目吗?也许您可以渲染部分集合并在滚动上渲染其他项目或使用分页或使用SlickGridWebix 的“虚拟scrioll”。

    2) 检查您重新渲染视图的频率。尝试减少导致重新渲染的事件数量

    3) 尽量减少 ItemView 的事件监听器数量。将上下文事件委托给 CollectionView 是一种很好的做法

    4) 您可以使用setTimeout 来按部分呈现集合。例如,您将 coll 分成 4 个部分除以 50 个项目,并引发 4 个超时来呈现它。

    5) 您可以优化下划线模板并摆脱with {} 运算符。 http://underscorejs.org/#template

    【讨论】:

      【解决方案3】:

      您的“billingCountryItemTpl”变量中有什么?如果它只是带有模板 ID 的字符串,那么您可以使用 Marionette.TemplateCache 预编译您的模板。

      所以你会有:

      template: Marionette.TemplateCache.get(billingCountryItemTpl)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 2013-07-11
        • 2014-05-16
        • 1970-01-01
        • 2014-06-05
        • 2012-11-23
        • 1970-01-01
        相关资源
        最近更新 更多