【问题标题】:How to avoid duplicate code and logic in templates for similar views in Backbone.js如何避免 Backbone.js 中类似视图的模板中的重复代码和逻辑
【发布时间】:2014-07-06 17:52:04
【问题描述】:

我正在使用backbone.js 构建一个应用程序,并发现自己在模型视图的模板中拥有一个包含大量条件逻辑的视图。模型的type 属性用于确定要渲染的html。如果可能的话,我想避免这种逻辑,因为它很难阅读。我认为有几种方法可以解决这个问题(请注意,我在这里得到的实际模板非常简化):

1.集合视图而不是模型视图中的条件逻辑 - 多个子视图

我可以将作用于每个模型类型的条件逻辑放入集合视图中:

var CollectionView = Backbone.View.extend({
    ....
    render: function() {
        this.collection.each(function(thing) {
            if(thing.get("type") === "wotsit") {
                this.$el.append(new WotsitView({ model: thing });
            } else if(thing.get("type") === "oojamaflip") {
                this.$el.append(new OojamaflipView({ model: thing });
            }
        }, this);
    },
    ....
}

优点 这样我就可以让每个子视图都有一个没有逻辑的模板方法,而只是构建 html。

var WotsitView = new Backbone.View.extend({
    ....
    template: _.template('<h2>{{ title }}</h2>');
});
var OojamaflipView = new Backbone.View.extend({
    ....
    template: _.template('<h3>{{ title }}</h3>');
});

缺点 问题是,集合中的things 都非常相似。每个thing事件 可能相同或非常相似,我可以看到有很多代码重复。我真的只希望这些子视图的实际模板与其他一切都相同。

2。模型视图中的条件逻辑 - 多种模板方法

var ModelView = Backbone.View.extend({
    ....
    render: function() {
        if(this.model.get("type") ==== "wotsit") {
            this.$el.html(this.wotsitTemplate(this.model.attributes));
        } else if(this.model.get("type") === "oojamaflip") {
            this.$el.html(this.oojamaflipTemplate(this.model.attributes));
        }
    },
    wotsitTemplate: _.template('<h2>{{ title }}</h2>'),
    oojamaflipTemplate: _.template('<h3>{{ title }}</h3>')
});

优点 该模型只有一个视图。 所有事件等都是一个视图中的句柄,而不是被复制。

缺点 我其实很喜欢这种方式,但我很想听听其他人的选择。

【问题讨论】:

  • 我强烈建议您查看 Marionette 或 Chaplin 源代码以获得有意义的答案。或者您可以将主干视图放在一起并使用支持复合视图的 React 或 Vue 库。主干视图组件是只是……不好。
  • @mpm 我真的很喜欢 Marionette。现在,我开始感觉到它并不像我想要的那样“强大”——我的意思是从代码的角度来看,而不一定是性能方面的。

标签: backbone.js templating


【解决方案1】:

选项 #1 = 多态性

选项 #2 = switch 语句

如果您从不(或很少)必须添加新类型,但您可能想要添加新方法,则 Switch 语句很有用。想象一下,您想向ModelView 添加一个validate 方法,该方法检查该模型的视图输入的正确性并将结果报告给用户。使用选项 #2,您只需添加一个新方法来打开模型类型(就像 render 方法一样)来处理验证。

现在假设我们已经有一个render 方法和一个validate 方法,并且我们想要处理一种新类型的模型,一个thingamajig。使用选项#2,您必须向rendervalidate 添加逻辑。现在想象一下,我们不仅有 2 种方法,还有 10 种方法——当您必须处理新类型时,选项 #2 变得非常复杂非常快。但是如果我们遵循选项 #1,那么无论有多少方法,我们只需要在一个地方创建一个新视图,然后更新 CollectionView 以将新类型映射到新视图。

大多数时候,多态性(选项#1)是干净的方式。它使您可以将特定于给定类型的所有逻辑分开并将其放在一个地方,从而可以轻松处理新类型。

保持干燥

如果您担心选项 #1 会导致所有视图之间出现大量重复代码,请不要忘记创建从其他主干视图继承的视图很容易:

var ItemView = Backbone.View.extend({
    initialize: function() {
        /* some common logic for all views */
    }
});
var WotsitView = ItemView.extend({
    template: _.template('<h2>{{ title }}</h2>')
});
var OojamaflipView = ItemView.extend({
    template: _.template('<h3>{{ title }}</h3>')
});

【讨论】:

  • 非常感谢您的回答@Michael。这很有帮助。我对 JavaScript 有点陌生,不知道你可以像上面那样实现选项 #1。很棒。
  • @Joe 没问题,我知道要弄清楚为什么有些设计比其他设计更好是多么困难。技术问题只需要聪明,但设计问题需要经验。
猜你喜欢
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-27
  • 2017-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多