0

我有一个 instrumentView ( instrumentView),它有一个 child measureView,它有 children measureRepView。我很难理解正确的 UI 组件创建、删除和更新(重新渲染)。

我当前的实现是将事件从 measureRepView 传递回 measureView 并让度量重新呈现其整个自身。(我这样做是因为我不确定如何重新渲染 measureRepView 并在子列表中保留其原始位置/顺序)。我通过相应的模型 CID 作为识别视图 el 的一种方式。

转换完成后,它measureView会重新渲染自己measureRepView,但是,似乎某些绑定丢失了,因为我不能measureRepView再次转换,而且我没有得到控制台打印。

我认为这与使用模板和/或 $el 定义的潜在非 BackBone 约定结构有关,或者我真正认为的问题是,measureRepView没有正确销毁,因此当一个绑定丢失measureRepView时改造后删除。

如果您需要其他代码,请告诉我,并感谢您对 BackBone 的帮助。

instrumentView

define([...], function(...){
  return Backbone.View.extend({
    el: $('.hTrack'),

    events : {...},

    initialize: function(options){
      ...
      this.render();
    },

    /*
      This View does not have its own html rendering, but instead creates
      a new MeasureView which gets rendered instead.
    */
    render: function(options){
      if(options) {
        var ƒthis = this;
        // for each of the measures (Current version should only have 1 Measure)
        _.each(this.hTrack.get('measures').models, function(measure, index) {
          new MeasureView({
            collectionOfMeasures: ƒthis.hTrack.get('measures'),
            parent: ƒthis.hTrack,
            parentEl: '#hTrack-'+ƒthis.hTrack.cid,
            model: ƒthis.hTrack.get('measures').models[index],
            currentMeasureRepresentation: options.representation
          });
        });
      }
      return this;
    }
  });
});

measureView

define([...], function(...){
  return Backbone.View.extend({    
    events : {...},
    initialize: function(options){
      //since we're being created by a HTrackView, we are passed in options.
      for (var key in options) {
        this[key] = options[key];
      }
      this.el = '#measure-container-'+options.parent.cid;

      //Dispatch listeners
      dispatch.on('reRenderMeasure.event', this.render, this);
      ....

      _.bindAll(this, 'render');
      this.listenTo(this.measureRepresentations, 'remove', _.bind(this.render, this));  
      this.listenTo(this.measureRepresentations, 'add', _.bind(this.render, this));  
      this.collectionOfMeasureReps.on('add', _.bind(this.render, this));
      this.collectionOfMeasureReps.on('remove', _.bind(this.render, this));
      this.model.on('change:scale', _.bind(this.render, this));

      this.render();
    },

    render: function(){
      this.scale = this.measureModel.get('scale');
      // Make a template for the measure and append the MeasureTemplate to the measure area in the hTrack
      var measureTemplateParameters = {
        mCID: this.model.cid,
        measureCount: this.measureCount,
        measureNumberOfBeats: this.model.get('beats').length
      };
      var compiledMeasureTemplate = _.template( MeasureTemplate, measureTemplateParameters );

      // If we are adding a rep, clear the current reps, then add the template
      $(this.el).html('');
      $(this.el).append( compiledMeasureTemplate )

      // for each rep in the measuresCollection
      _.each(this.measureRepresentations.models, function(rep, repIndex) {
        // (when representation button changes, the current representation template will get updated)
        // compile the template for a measure

        var measureRepViewParameters = {...};
        new MeasureRepView(measureRepViewParameters);
      }, this);

      return this;
    }
  });
});

measure.html(模板):

<div id="measure<%= mCID %>" class="measure">
  <div class="add-measure"><i class="icon-plus"></i></div>
  <div class="remove-measure"><i class="icon-minus"></i></div>
  <div id="measure-rep-container-<%= mCID %>" class="pull-left measure-rep-container"></div>
</div>

measureRep

define([...], function(...){
  return Backbone.View.extend({
    events : {
      'click .delta' : 'transitionRepresentation'
    },
    initialize : function(options){
      //if we're being created by a MeasureView, we are
      //passed in options. Otherwise we create a single
      //measure and add it to our collection.
      for (var key in options) {
        this[key] = options[key];
      }
      this.repContainerEl = options.measureRepContainer;

      //Dispatch listeners   
      this.listenTo(this.model, 'change', this.transition, this);

      this.render();
    },
    templateParameters : function(options){
      return {
        measureRepID: 'measure-rep-'+options.measureRepModel.cid,
        measureClasses: 'measureRep measure-'+this.model.get('representationType'),
        measureRepDeltaID: 'delta-'+this.measureRepModel.cid,
        measureRepSVGID: 'svg-'+this.measureRepModel.cid,
        svgClasses: this.model.get('representationType'),
        measureRepType: this.model.get('representationType'),
        beatHolderID: 'beat-holder-'+this.measureRepModel.cid,
        secondaryBeatHolderID: 'secondary-beat-holder-'+this.measureRepModel.cid,
        beatFactoryHolderID: this.beatFactoryHolder,
        measureCount: this.measureCount,
        measureRep: this.model.get('representationType'),
        measureRepRecordID: 'record-'+this.measureRepModel.cid
      }
    },

    beadToBar: function(){
      setTimeout(function(){...}, this.animationIntervalDuration );
      // Here, once the animation transformation is done, I want to ultimately have the new representation replace the current representation. 
      // I have tried including this.remove()
      setTimeout(function(){
        dispatch.trigger('reRenderMeasure.event', this);
      }, this.animationIntervalDuration*2 );
    },

    render: function(){
      var ƒthis = this;

      //set the el for JQ-UI Drag
      // may not be needed
      this.$el.attr('id', 'measure-rep-' + this.measureRepModel.cid);

      // compile the template for a representation
      var compiledTemplate = _.template( MeasureRepTemplate, this.measureRepTemplateParameters );
      // put in the rendered template in the measure-rep-container of the measure
      $(this.repContainerEl).append( compiledTemplate );

      this.setElement($('#measure-rep-'+this.measureRepModel.cid));

      // make the beats (another function that makes beatViews and place them in this measureRepView
      this.makeBeats();

      return this;
    },

    //This looks at the previous representation type, and calls the appropriate function to transition it into the new representation
    transition: function(){
      var PRT = this.model.get('previousRepresentationType');
      var CRT = this.model.get('representationType');

      if (PRT == 'audio'){
        if(PRT == 'bead'){
        if (CRT == 'audio'){
          this.beadToAudio();
        } else if(CRT == 'line'){
          this.beadToLine();
        } else if(CRT == 'pie'){
          this.beadToPie();
        } else if(CRT == 'bar'){
          this.beadToBar();
        }
      } 
    }

  });
});

measureRep.html(模板):

<div id="<%= measureRepID %>" class="<%= measureClasses %>" data-representation="<%= measureRepType %>">
  <div class="row-fluid">
    <div id="<%= measureRepDeltaID %>" class="delta btn pull-left">&Delta;</div>
    <div class="remove-measure-rep pull-right"><i class="icon-minus"></i></div>
  </div>
  <svg id="<%= measureRepSVGID %>" xmlns="http://www.w3.org/2000/svg" version="1.1" class="<%= svgClasses %>">
    <g class="beatHolder" id="<%= beatHolderID %>" transform="translate(0,0)"></g>
    <g class="secondaryBeatHolder" id="<%= secondaryBeatHolderID %>" transform="translate(0,0)"></g>
    <g class="beatFactory" id="<%= beatFactoryHolderID %>"></g>
  </svg> 
  <% if ( measureRep == 'audio') { %>
    <div class="pause"><i id="<%= measureRepRecordID %>" class="record-button icon-hand-down icon-2x"></i></div>
  <% } else { %>

  <% } %>
</div>
4

0 回答 0