我有一个 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">Δ</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>