Backbone.js每个属性渲染(多个小视图与每个视图多个模板)

Backbone.js每个属性渲染(多个小视图与每个视图多个模板),backbone.js,render,backbone-views,Backbone.js,Render,Backbone Views,我有一个模型和一个视图。该视图显示模型的属性,并允许用户操作这些属性。问题是当一个属性被修改时,它会重新呈现整个视图,这给我带来了很多问题 文本输入上的示例模糊事件将新输入保存到属性,从而触发渲染。这意味着,如果用户从该文本输入直接单击同一视图上的按钮,该事件将永远不会触发,因为触发的第一个事件将模糊,导致整个视图重新渲染,从而丢失按钮单击事件 我有两个想法: 具有单个视图,其中每个属性都位于单独的模板中。然后我绑定到一个特定的属性更改事件,并在render中只更新更改属性的html。这看起来像

我有一个模型和一个视图。该视图显示模型的属性,并允许用户操作这些属性。问题是当一个属性被修改时,它会重新呈现整个视图,这给我带来了很多问题

文本输入上的示例模糊事件将新输入保存到属性,从而触发渲染。这意味着,如果用户从该文本输入直接单击同一视图上的按钮,该事件将永远不会触发,因为触发的第一个事件将模糊,导致整个视图重新渲染,从而丢失按钮单击事件

我有两个想法:

  • 具有单个视图,其中每个属性都位于单独的模板中。然后我绑定到一个特定的属性更改事件,并在render中只更新更改属性的html。这看起来像是一种黑客行为,因为强制视图只更新更改的属性需要做很多工作。它会给已经很复杂的视图增加很多不必要的复杂性
  • 创建由视图组成的主视图,其中每个视图表示模型的属性。这将创建大量视图,几乎没有任何功能
    我似乎更喜欢2号。选项你怎么认为?最佳实践是什么?有没有更好的方法来处理这个问题?

    我想你可以很容易地做到这一点

    退一步,想想你在哪里绑定你的事件。似乎是将它们直接绑定到每个单独的元素之上,而不是使用父委托

    这里有一个例子

    Backbone.View.extend({
      el: $("div.parent"),
      events: function() {
        this.$el.on("click", "input[type=button]", function(){});
        // jquery cross browser on this
        this.$el.on("blur", "input[type=text]", function(){});
      },
      initialize: function() {
        this.model.bind("change", this.render, this);
      },
      render: function() {
        this.$el.html('<input type="text" /><input type="button" />');
      }
    });
    
    Backbone.View.extend({
    el:$(“部门母公司”),
    事件:函数(){
    这个.$el.on(“单击”,“输入[type=button]”,function(){});
    //jquery跨浏览器访问此服务器
    这个.el.on(“blur”,“input[type=text]”,function(){});
    },
    初始化:函数(){
    this.model.bind(“change”,this.render,this);
    },
    render:function(){
    此.$el.html(“”);
    }
    });
    
    这是el和它的结构

    <div class="parent">
      <input type="text" />
      <input type="button" />
    </div>
    
    
    

    因此,$el指向div.parent。我可以不断地重新加载此文件的内容。$el,只要html结构不变,我就不必担心事件会被解除绑定。另一个解决方案是,如果我真的不能进行委派,我会在再次渲染时调用events方法。

    就像您自己所说的,您的两个选项似乎都非常复杂。但有时额外的复杂性是一种必然的罪恶。但是,如果更新的字段相对简单(比如将值绑定到元素或输入字段),我只需更新DOM元素,而无需在其上创建额外的视图/模板抽象

    假设你有一个模型:

    var person = new Person({ firstName: 'John', lastName: 'Lennon', instrument:'Guitar' });
    
    以及呈现以下模板的视图:

    <div>First Name: <span class="firstName">{{firstName}}</span></div>
    <div>Last Name: <span class="lastName">{{lastName}}</span></div>
    <div>Instrument: <input class="instrument" value="{{instrument}}"></input></div>
    
    这样的解决方案不能扩展到非常复杂的视图,因为您必须向DOM中添加分类元素,并在视图代码中维护它们。但对于较简单的情况,这可能非常有效

    此外,如果多个较小的视图自然地划分为多个部分,那么尝试组合这些视图总是很好的。这样可以避免单独更新单个字段。

    有关类似问题,请参阅
    var PersonView = Backbone.View.extend({
    
      //convention: propertyName+"Changed"
      //specify handler as map of selector->method or a function.
      firstNameChanged:  { '.firstName': 'text' },
      lastNameChanged:   { '.lastName': 'text' },
      instrumentChanged: { '.instrument': 'val' },
      otherFieldChanged: function(val) { //do something else },
    
      initialize: function (opts) {
        this.model.on('change', this.update, this);
      },
    
      //called when change event is fired
      update: function(state) {
        _.each(state.changed, function(val, key) {
          var handler = this[key + "Changed"];
          //handler specified for property?
          if(handler) {
            //if its a function execute it
            if(_.isFunction(handler)) {
              handler(val);
            //if its an object assume it's a selector->method map
            } else if(_.isObject(handler)) {
              _.each(handler, function(prop, selector) {
                this.$(selector)[prop](val);
              }, this);              
            }
          }
        }, this);
      }