所有视图逻辑都应该放在模板中吗?

时间:2015-02-18 18:21:32

标签: javascript templates backbone.js handlebars.js

例如,当视图的模型不是新的(具有id)时,我需要禁用每个输入。

我能做到:

if(!view.model.isNew()) { view.$('input, select, textarea').prop('disabled', true); }

或者我可以在模板中的每个输入上执行“if”:

<input type="text" {{# if model.id }}disabled{{/ if }}/>

如果我们遵循MVC(或MVP)模式,我猜第二种方法是最好的,因为视图逻辑在视图中。但是,如果我采用这种方法并决定更改禁用输入的条件,我需要为每个模板中的每个输入更改它。如果我留下JS代码,只有一个地方可以改变。

这只是一个例子,但我遇到了类似的困境。希望你能得到答案。

干杯!

3 个答案:

答案 0 :(得分:1)

基于你的问题,我会说你可能因为两个相关原因而遇到这个普遍问题 -

  1. 您只使用骨干网,而不是像MarionetteChaplin这样的框架。
  2. 您的观点“太大”,并试图将过多的资料合并到一个视图中。
  3. 我几乎从未将逻辑包含在模板中,因为我几乎从不需要。那是因为我写了很多非常小的视图,并且将它们拼凑在一起以制作大视图Marionette's view classes通过subclassing the backbone view into different view types添加额外的实用工具并彻底减少样板,使这很容易实现。 Marionette也非常擅长处理嵌套视图,它实际上允许您向下钻取并创建特定用例所需的精确视图工具。

    能够在1-2行代码中使用Marionette定义有用的视图并不常见,这使您可以灵活地制作非常小巧,高效的视图。制作大量小视图的缺点是编写的代码很多,并且可能难以维护,但是Marionette makes that disadvantage relatively insignificant。 Marionette只花了我几天的时间来解决这个问题,我强烈建议将它集成到你的Backbone应用程序中以解决这个问题。

    当您的观点很大并且尝试做太多时,您最终会遇到您所描述的问题 - 您必须对其进行过多修改以满足您的特定需求并且您的代码会获得丑陋,难以阅读。当你有很多小视图时,它们非常敏感,并且几乎不需要任何自定义。

    我认为,您的问题的例子是边界线情况。我的直觉是创建两个完全独立的视图,并在以下伪代码下运行它们:

    editableView = { //definition }}
    disabledView = { //definition }}
    
    if (newModel)
        editableView.render()
    else
        disabledView.render()
    

    这是我的直觉,因为我的赌注是视图之间存在其他差异,而不是输入是否可编辑。即使现在没有,您可能会在几个月后发现您的需求已经发生变化,并且您希望加入一些更改。我建议的方法允许您将这些更改直接放入相应的视图中,而不必担心在单个视图中将它们记录下来并确定该逻辑是属于模板还是视图。

    如果您绝对肯定两个观点之间的唯一差异将是输入是否可编辑,并且您的需求不会改变未来,那么也许你会想要用相同的视图来渲染它们。如果是这种情况,我建议您根据您确定的原因将逻辑放在javascript中,而不是放在模板中。但正如我所说,你的例子确实是一个边缘情况,在大多数情况下,我认为你会发现缩小你的观点范围将真正帮助你看到你的“模板逻辑”所属的位置。

    注意:我在这个答案中谈了很多关于木偶的事情,但我也提到卓别林是上面的另一种选择。我对卓别林没有多少经验,但你可能想把它作为木偶替代品来考虑。

答案 1 :(得分:0)

我更喜欢在模板中实现视图逻辑:

  1. 更容易更改和阅读
  2. 对id,元素等的任何依赖都可以在模板
  3. 中实现
  4. 列表项
  5. 复杂逻辑可以在marionette的templateHelper或Backbone的serializeData中实现,而不依赖于模板或视图的内容
  6. 您还可以使用Handlebar Helper实现复杂逻辑
  7. 代码中视图逻辑的缺点是:

    1. 如果选择器(id,类等)发生更改,则必须更改或查看所有视图
    2. 如果重新呈现视图,则必须再次应用
    3. 逻辑

答案 2 :(得分:0)

也许你可能正在寻找presenter(又名装饰者)。

不要直接向模板发送模型,而是考虑通过演示者发送模板,这样就可以构造输入字段的属性。像这样:

present = function(model) {
  return {
    inputAttributes: model.isNew() ? 'disabled' : '',
    id: model.id,
    name: 'Foobar'
  }
}

template(present(model));

然后在你的模板中:

<input type="text" {{inputAttributes}}>