所以我有一个表格出现在几页上,包含许多输入组。说组a,组b和组c。在某些页面上,他们可能有a和b,而在其他页面上,表单包含b和c。每个组可能需要自己的客户端自定义验证,可以从表单控制器执行。
使用骨干和牵线木偶实现这一目标的最佳方法是什么?
从概念上讲,我对两者都相当陌生,我假设我需要一个FormController,它是从一个特定于页面的Controller实例化的,它还实例化了我对该页面所需的组控制器。任何建议都会很棒。
答案 0 :(得分:1)
要使这项工作,您将为每个输入组创建两个对象。一个用于其自定义功能,另一个用于其事件。在表单控制器中,您使用基本表单视图_.extend
每个输入组的函数对象,以将自定义函数放入新的表单视图中。接下来,您将自定义events
对象传递到新表单视图的构造函数中,其中基本视图的实用程序功能会将新的自定义事件添加到基本表单视图事件中。最后,您必须确保您拥有包含正确输入组的表单的模板。
我还应该提一下,您可以使用Marionette.LayoutViews
和动态区域以可能更清晰的方式完成此操作(您可以为每个输入组指定原子模板),尽管需要更多开销。
我已经习惯了这个想法了。我最近一直在考虑使用Underscore _.extend()
将库存功能插入到不同的视图中。您的问题对于此解决方案来说是理想的。以下是您如何实施它的示例。
假设您的输入组A具有执行该功能的验证功能
validateA: function () {
// custom validation routine
},
和一个处理表单提交的提交函数,
submitA: function () {
// custom submit routine
}
您要做的第一件事就是将这些函数打包在一个对象中:
groupA = {
validateA: function() {...},
submitA: function() {...}
}
您拥有与输入组一样多的功能对象。
您还可以构建一个通用表单视图,该视图将包含常用表单功能,并且还可以用作您用于呈现表单的基本视图
var GenericForm = Backbone.Marionette.ItemView.extend({...});
在这里,您将把所有基线事件和功能放在所有表格中。
然后,如你所说,你设置了一个FormController,它会插入自定义功能,就像这样,
var formController = function () {
callFormZ: function() {
var genericForm = new GenericForm({ groupEvents: [eventsA, eventsB] });
var formZ = _.extend(genericForm, groupA, groupB);
SomeRegion.show(formZ);
}
}
在基本视图和两个输入组上使用_.extend
,最终得到一个新视图,formZ
,它是两个输入组的组合。如果您查看内部,它将具有GenericForm
加上
{
validateA: function () { ... },
submitA: function () { ... },
validateB: function () { ... },
submitB: function () { ... },
}
此时,虽然无法将任何事件绑定到自定义函数。
你可能已经注意到我在callFormZ控制器中传入了一个名为groupEvents
的属性中的数组。这些是输入组的自定义事件。它们通常具有
eventsA: {
'blur .groupA': 'validateA',
'click #groupA button': 'submitA'
}
理想情况下,我们只需使用extend来按照我们的功能方式合并您的事件。但是,由于我们希望在您的视图中只有一个events
属性,因此我们遇到了问题。 _.extend
将使用传递到events
的最后一个对象的events
属性覆盖视图对象中的所有_.extend
属性。因此,为了解决这个问题,我们必须传递一组自定义事件,每个表单组都有一个。
首先,您要为您正在使用的特定表单创建自定义事件的事件对象配置数组,
customEvents = [
eventsA: {
'blur .groupA': 'validateA',
'click #groupA button': 'submitA'
},
eventsB: {
'blur .groupB': 'validateB',
'click #groupB button': 'submitBA'
}];
您将此数组传递给构造函数,就像我们在callFormZ控制器函数中所做的那样。现在,数组将加载到您的options参数中。在初始化中,您可以调用类似的内容,
initialize(options) {
combineEvents(options.groupEvents);
this.delegateEvents();
}
其中,combinedEvents
是
combineEvents: function() {
var extendEvents = [this.eventsA, this.eventB]; // Make an array of the extended groups
_.each(extendEvents, function (extendEvent) {
for (prop in extendEvent)
this.event[prop] = extendEvent[prop];
}
}
另外,请注意,在合并事件后,我调用了delegateEvents
,以便我们重新接收新事件。
要完成所有这些工作,您必须提供包含每个输入组部分的模板。我不知道我们如何从各个输入组模板以编程方式构建模板。相反,您必须拥有一个模板,其中输入组与表单相关。
因此,为了完成这项工作,您将为每个输入组创建两个对象。一个用于其自定义功能,另一个用于其事件。在表单控制器中,您使用基本表单视图_.extend
每个输入组的函数对象,以将自定义函数放入新的表单视图中。接下来,您将自定义events
对象传递到新表单视图的构造函数中,其中基本视图的实用程序功能会将新的自定义事件添加到基本表单视图事件中。最后,您必须确保您拥有包含正确输入组的表单的模板。