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

时间:2014-06-10 07:31:58

标签: javascript backbone.js marionette backbone-views backbone-events

我正在使用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监听

1 个答案:

答案 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);
},