触发器从marionitte的布局视图触发时多次调用被调用的函数

Trigger invokes the called function multiple time when fired from layout view in marionitte

本文关键字:调用 函数 marionitte 布局 视图 触发器      更新时间:2023-09-26

我正在使用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由fromunjob监听一旦成功触发一个触发器返回到sourceJobview由runJob监听多次调用

这个问题最常见的原因是僵尸视图——它们已经从DOM中移除,但是它们的事件处理程序仍然是绑定的。

您应该使用listenTo而不是on来绑定事件。这允许木偶的View.close方法在视图关闭时清理旧的事件处理程序。

这是一个简单的修复:

initialize: function(){
  this.listenTo(options.changeInfo.vent, "job-selected", this.runJob);
},