优雅的方式来包装多个Backbone渲染方法,以避免“之前”和“之后”事件重复?

时间:2013-05-01 22:40:41

标签: javascript jquery backbone.js underscore.js marionette

我已经将我的View上的render()方法划分为两个单独的方法,以便允许我渲染整个视图,或者只显示由HTML表单表示的视图的一小部分。两个render()方法看起来像这样:

    render: function () {
        var templateData = _.extend({}, this.model.attributes, localizedText),
            compiledLoadStopTemplate = Handlebars.compileClean(template);

        this.isClosed = false;

        this.triggerMethod("before:render", this);
        this.triggerMethod("item:before:render", this);

        this.$el.html(compiledLoadStopTemplate(JSON.parse(JSON.stringify(templateData))));
        this.renderAppointmentForm();

        this.bindUIElements();

        this.showStatusNotification();

        this.triggerMethod("render", this);
        this.triggerMethod("item:rendered", this);

        return this;
    },
    renderAppointmentForm: function () {
        var templateData = _.extend({}, this.model.attributes, localizedText, { notification: this.notification }),
            compiledAppointmentFormTemplate = Handlebars.compileClean(appointmentFormTemplate);

        this.triggerMethod("before:render", this);
        this.triggerMethod("item:before:render", this);

        this.$el.find(".hook-appointment-form-container").html(compiledAppointmentFormTemplate(JSON.parse(JSON.stringify(templateData))));

        this.bindUIElements();

        this.showStatusNotification();

        this.triggerMethod("render", this);
        this.triggerMethod("item:rendered", this);

        return this;
    },

现在,这里有很多重复的代码;虽然模板数据,模板和实际html()调用是唯一的,但几乎所有其他行在它们之间都是通用的。

有一个包装方法可以让我提供模板数据,编译模板和html()行,并自动使用其他其他的前/后触发方法普遍地,但是我无法使用真正起作用的Underscore的wrap()来设计方法。

我确信有一个更高级的编程概念可以完美地满足这个需求,但它现在正在避开我的掌握。

2 个答案:

答案 0 :(得分:2)

如何在单独的视图中提取表单?如果不可能,那么我有这个建议:

loadStopTemplate: Handlebars.compileClean(template),

appointmentFormTemplate: Handlebars.compileClean(appointmentFormTemplate),

getTemplateAttributes: function () {
    var attributes = _.extend({}, this.model.attributes, localizedText, { notification: this.notification });
    return JSON.parse(JSON.stringify(attributes))
},

render: function () {
    this.isClosed = false;
    return this.enterRenderState(function (attributes) {
        this.$el.html(this.loadStopTemplate(attributes));
        this._renderForm(attributes);
    })
},

renderAppointmentForm: function () {
    return this.enterRenderState(this._renderForm)
},

_renderForm: function (attributes) {
    this.$('.hook-appointment-form-container')
        .html(this.appointmentFormTemplate(attributes))
    return this;
},

enterRenderState: function (callback) {
    this.triggerMethod("before:render", this);
    this.triggerMethod("item:before:render", this);
    callback.call(this, this.getTemplateAttributes());
    this.bindUIElements();
    this.showStatusNotification();
    this.triggerMethod("render", this);
    this.triggerMethod("item:rendered", this);
    return this
}

答案 1 :(得分:1)

一种可以轻松重构的方法是创建一个辅助函数来完成所有常用功能,然后只传入一些不同部分的函数。

例如

render: function () { 
var templateData = _.extend({}, this.model.attributes, localizedText),
        compiledLoadStopTemplate = Handlebars.compileClean(template);
    var self = this;

    var isClosed = function () {
        self.isClosed = false;
    }

    var renderHTML = function () {

     self.$el.html(compiledLoadStopTemplate(JSON.parse(JSON.stringify(templateData))));

    }

    return this.renderHelper(renderHTML, isClosed);
}

renderAppointmentForm: function () {

       var templateData = _.extend({}, this.model.attributes, localizedText, { notification: this.notification }),
        compiledAppointmentFormTemplate = Handlebars.compileClean(appointmentFormTemplate);

    var renderHTML = function () {
        self.$el.find(".hook-appointment-form-container").html(compiledAppointmentFormTemplate(JSON.parse(JSON.stringify(templateData))));
    }

    return this.renderHelper(renderHTML);
}


renderHelper: function (renderHTML, isClosed) {

    if (isClosed) {
        isClosed();
    }

    this.triggerMethod("before:render", this);
    this.triggerMethod("item:before:render", this);

    renderHTML();

    this.triggerMethod("render", this);
    this.triggerMethod("item:rendered", this);

    return this;

}