我正在使用marionitte框架,我试图从一个布局视图触发一个触发器到任何其他视图,但是在另一个视图上的函数被多次调用,即使触发器只被触发一次。
是否有人遇到过相同的问题并已解决,请让我知道解决方案,以便我可以在我的代码中使用。
w.src.SourceTabView = Backbone.Marionette.Layout.extend({
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template: "#src-template-source-tab-view",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
regions: {
"change results" : "#src-template-change-results-region",
"change pagination" : "#src-template-change-pagination-region",
"document layout" : "#src-template-document-layout-region",
"workflow detail" : "#src-template-workflow-detail-region",
"job log" : "#src-template-job-log-region",
"source job" : "#src-template-job-region"
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
changeInfo: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mostRecentChange: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
screenCapture: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
regionSelector: null,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
tab: "details",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
controls: {
institution: new w.EntitySelector(null,[]),
contentSetGroup: new w.EntitySelector(null,["cs"]),
pageTypes: new w.EntitySelector(null,["page_type"]),
prevTypes: new w.EntitySelector(null,["previous_type"])
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
initialize: function(){
this.listenTo( this.model , 'sync' , this.render );
var instTypes = [] ;
for( var instTypeEntityId in w.INST_TYPES ){
instTypes.push(instTypeEntityId);
}
this.controls.institution = new w.EntitySelector(null,instTypes);
this.controls.institution.minValueLength = 1;
this.controls.contentSetGroup.maxValueLength = 1;
this.controls.contentSetGroup.minValueLength = 1;
this.controls.prevTypes.minValueLength = 1;
this.controls.prevTypes.maxValueLength = 1;
this.fetchMostRecentChange();
this.regionSelector = null;
this.changeInfo = new w.src.ChangeInfo(this.model);
this.changeInfo.vent.on("change-selected", this.render);
this.changeInfo.vent.on("change-refreshed", this.render);
this.changeInfo.vent.on("workflow-selected", this.render);
this.changeInfo.vent.on("workflow-refreshed", this.render);
this.changeInfo.vent.on("jobLog-view", this.render);
this.changeInfo.vent.on("workflow-created", w.refreshWorkflows);
this.changeInfo.vent.on('save-source', this.fromJobRun, this);
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
fetchMostRecentChange: function(){
var self = this;
$.ajax({
url: "/source/" + self.model.id + "/most-recent-change",
dataType: "json",
success: function(mostRecentChange){
if( mostRecentChange ){
$.ajax({
url: "/document?change=" + mostRecentChange.id + "&rendering=screen-capture",
dataType: "json",
success: function(response){
self.mostRecentChange = mostRecentChange;
if( response.results.length > 0 ){
self.screenCapture = response.results[0];
}
self.render.call(self);
}
});
}
}
});
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
serializeData: function(){
var verificationDate = this.model.get('verificationDate');
// Converting timestamp into readable format
if(!verificationDate) {
verificationDate = '';
} else {
verificationDate = moment(verificationDate).format('MM/DD/YYYY');
}
return {
model: this.model,
tab: this.tab,
minimumChangeInterval: this.humanizeDate(this.model.get("minimumChangeIntervalMs")),
verificationDate: verificationDate
}
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
onRender: function(){
var tabRegion = localStorage.getItem("tabRegion"),
rememberTabs = localStorage.getItem("rememberTabs");
if( tabRegion && rememberTabs === "true"){
this.tab = tabRegion;
} else if( this.tab == null ) {
this.tab = "details";
}
localStorage.setItem("tabRegion", this.tab);
// content set group
var contentSetIds = [];
for( var contentSetId in w.CS ){
if( this.model.get("entityIds").indexOf(contentSetId) >= 0 ){
contentSetIds.push(contentSetId);
}
}
this.controls.contentSetGroup.values = contentSetIds;
this.controls.contentSetGroup.bind(this.$("#src-tab-details-group"));
// page types
var pageTypeIds = [];
for( var pageTypeId in w.PAGE_TYPES ){
if( this.model.get("entityIds").indexOf(pageTypeId) >= 0 ){
pageTypeIds.push(pageTypeId);
}
}
this.controls.pageTypes.values = pageTypeIds;
this.controls.pageTypes.bind(this.$("#src-tab-details-page"));
// prev types
var prevTypeIds=[];
for(var prevTypeId in w.PREV_TYPES){
if(this.model.get("entityIds").indexOf(prevTypeId)>=0){
prevTypeIds.push(prevTypeId);
}
}
this.controls.prevTypes.values = prevTypeIds;
this.controls.prevTypes.bind(this.$("#src-tab-details-previousType"));
// changes
var changePaginationView = new w.PaginationView({collection:this.changeInfo.changes});
changePaginationView.autoHide = true;
this["change results"].show(new w.src.ChangeCollectionView({collection:this.changeInfo.changes, changeInfo:this.changeInfo}));
this["change pagination"].show(changePaginationView);
// institution
var institutionIds = [];
_.each(this.model.get("entityIds"),function(entityId){
if( !w.INST_TYPES[entityId] && !w.PAGE_TYPES[entityId] && !w.CS[entityId] && !w.PREV_TYPES[entityId]){
institutionIds.push(entityId);
}
});
this.controls.institution.values = institutionIds;
this.controls.institution.bind(this.$("#src-tab-details-institution"));
// job
this["source job"].show(new w.src.SourceJobView({changeInfo:this.changeInfo}));
// documents
if( this.changeInfo.selectedChange ){
var documentLayoutView = new w.src.DocumentLayoutView({collection:this.changeInfo.documents, changeInfo:this.changeInfo});
this["document layout"].show(documentLayoutView);
var documentPaginationView = new w.PaginationView({collection:this.changeInfo.documents});
documentPaginationView.autoHide = true;
documentLayoutView["document results"].show(new w.src.DocumentCollectionView({collection:this.changeInfo.documents, changeInfo:this.changeInfo}));
documentLayoutView["document pagination"].show(documentPaginationView);
} else {
this["document layout"].close();
}
//view job logs
if(this.changeInfo.viewDetails) {
var self = this;
var jobId = this.changeInfo.selectedChange.get('jobId');
var selectedJobModel = new w.Job({id: jobId});
selectedJobModel.fetch({ success: function(model) {
self["job log"].show(new w.src.JobLogView({logger: model.get('logger')}));
}});
}
// workflow detail
this["workflow detail"].show(new w.src.WorkflowDetailView({changeInfo:this.changeInfo}));
// other setup
this.onUrlType();
this.setTab();
if(!this.model.isNew()) {
this.validate();
}
if(this.model.get("includedRegions").length) {
this.$(".delete-all-selected-region").removeClass("disabled");
}
// Adding datepicker
this.$("#verificationDate").datepicker({
todayHighlight: true,
autoclose: true
});
},
fromJobRun: function() {
var self = this;
this.onUseMyAccountClick();
this.populateDateToModel();
// save the model
this.model.save().success(function() {
self.onSuccess();
self.changeInfo.vent.trigger("job-selected");
}).error(function(response) {
self.onError(response)
});
},
});
sourceJobView.js
w.src.SourceJobView = Backbone.Marionette.Layout.extend({
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template: "#src-template-source-job-view",
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
initialize: function(){
this.options.changeInfo.vent.on("job-selected", this.runJob );
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
onRender : function(){
// decide whether to show the job details link
if( w.IS_ADMIN ){
this.$(".jobDetailsMessage").show();
} else {
this.$(".jobDetailsMessage").hide();
}
} ,
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
serializeData: function(){
return this.options.changeInfo;
},
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
runJob: function() {
console.log('here');
},
onRunJobClick: function() {
this.options.changeInfo.vent.trigger("save-source");
}
});
根据这里的代码 在sourceJobview触发的Onrunjobclick被触发到sourceTabview,它被fromrunJob监听,成功触发一个触发器返回sourceJobview,由多次调用的runJob监听
答案 0 :(得分:0)
此问题的最常见原因是zombie views - 它们已从DOM中删除,但它们的事件处理程序仍然受限制。
您应该使用listenTo
代替on
来绑定事件。当观看结束时,这允许Marionette的View.close
方法clean up old event handlers。
这是一个简单的解决方法:
initialize: function(){
this.listenTo(options.changeInfo.vent, "job-selected", this.runJob);
},