【问题标题】:Form controller in marionette木偶中的表单控制器
【发布时间】:2015-02-16 16:32:58
【问题描述】:

所以我有一个出现在几页上并包含许多输入组的表单。说a组、b组和c组。在某些页面上,它们可能有 a 和 b,而在其他页面上,表单包含 b 和 c。每个组可能需要其自己的客户端自定义验证,可以从表单控制器执行。

使用骨干和牵线木偶实现这一目标的最佳方法是什么?

从概念上讲,我对两者都很陌生,我假设我需要一个从特定于页面的控制器实例化的 FormController,该控制器还实例化该页面所需的组控制器。任何建议都会很棒。

【问题讨论】:

    标签: backbone.js marionette


    【解决方案1】:

    TL;DR

    要完成这项工作,您需要为每个输入组创建两个对象。一种用于其自定义功能,另一种用于其事件。在表单控制器中,您将_.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'
    }
    

    理想情况下,我们只使用扩展来合并您的事件,就像我们执行您的功能一样。但是,由于我们希望在您的视图中只得到一个 events 属性,因此我们遇到了问题。 _.extend 将使用传入_.extend 的最后一个对象的events 属性覆盖视图对象中的所有events 属性。所以为了解决这个问题,我们必须传递一组自定义事件,每个表单组一个。

    首先,您将使用您正在使用的特定表单的自定义事件创建一个事件对象的配置数组,

    customEvents = [
      eventsA: {
          'blur .groupA': 'validateA',
          'click #groupA button': 'submitA'
     },
     eventsB: {
          'blur .groupB': 'validateB',
          'click #groupB button': 'submitBA'
     }];
    

    您可以将此数组传递给您的构造函数,就像我们在 callFormZ 控制器函数中所做的那样。该数组现在将加载到您的选项参数中。在你的初始化中,你可以调用这样的东西,

    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 对象传递到新表单视图的构造函数中,其中基本视图的实用函数会将新的自定义事件添加到基本表单视图事件中。最后,您必须确保该表单的模板包含正确的输入组。

    【讨论】:

    • 感谢您抽出宝贵时间@Seebiscuit 这很有帮助,也是我们最终实施它的方式。
    • 酷。如果我必须在此和使用Regions(即通过LayoutView)之间进行选择,这可能也是我的做法。一旦您将功能抽象到视图中并插入到区域中,您需要在子视图和布局视图之间实现消息传递模式,这会增加另一层复杂性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多