Ember.js:如何建模这个例子?

时间:2013-11-14 20:13:09

标签: javascript architecture ember.js

我试图找出正确的Ember.js模型这个项目的方法,例如。需要什么型号,路线和控制器。 I have started a jsBin to work from

我的要求可以安全地降低到:

项目&他们的选择

  • 项目有一系列选项
  • 选项有自己的属性
  • 项目具有仪表板将使用的其他属性(选项旁边)

控制台

  • 仪表板没有任何自己的数据
  • 仪表板需要观察所有项目和选项,并更新其属性分析

导航

  • 几乎没有
  • 这将显示在一个“页面”上,但将来可能会添加少量页面/弹出窗口
  • 我希望能够保存并重新填充给定的状态(例如,选定的选项ID列表)

数据

  • 使用单个json调用
  • 将加载一次数据
  • 应用程序逻辑将仅在Ember中的客户端完成 - 没有业务逻辑的ajax
  • 服务器的唯一后续联系是if / when用户保存状态

那么在Ember中如何构建呢?

我曾经尝试过一次这样做,但这是我的第一次尝试,最后我得到了一个非常丑陋的设置。我想看看Ember经验的人会如何接近这个:

jsBin样机(link

我已经创建了一系列车把模板,但没有尝试应该存在哪些型号以及需要哪些控制器。 Screenshot of jsBin mockup

的Json

{
  "Items" : [
    {
      "Item" : {
        "nid" : "3",
        "title" : "Hydro",
        "image" : "http://bpf.vm/sites/default/files/bpf_things/hydro.jpg",
        "properties" : "Baseload, Intermittent",
                "values" : {
                    "Cost" : {
                        "price" : "6",
                        "quantity" : null
                    },
                    "Percent of Portfolio" : {
                        "price" : null,
                        "quantity" : "56"
                    }
                },
                "options" : {
                    "1" : {
                        "price" : "1512",
                        "quantity" : "10000"
                    },
                    "12" : {
                        "price" : "825",
                        "quantity" : "20000"
                    },
                    "11" : {
                        "price" : "550",
                        "quantity" : "50000"
                    }
                }
      }
    },
    {
      "Item" : {
        "nid" : "4",
        "title" : "Nuclear",
        "image" : "http://bpf.vm/sites/default/files/bpf_things/nuclear.jpg",
        "id" : "",
        "properties" : "Baseload, Predictable",
                "values" : {
                    "Cost" : {
                        "price" : "8",
                        "quantity" : null
                    },
                    "Percent of Portfolio" : {
                        "price" : null,
                        "quantity" : "21"
                    }
                },
                "options" : {
                    "4" : {
                        "price" : "825",
                        "quantity" : "10000"
                    },
                    "13" : {
                        "price" : "411",
                        "quantity" : "15000"
                    }
                }
      }
    },
    {
      "Item" : {
        "nid" : "5",
        "title" : "Natural Gas",
        "image" : "http://bpf.vm/sites/default/files/bpf_things/gas.jpg",
        "id" : "9",
        "properties" : "Baseload, Predictable",
                "values" : {
                    "Cost" : {
                        "price" : "5",
                        "quantity" : null
                    },
                    "Percent of Portfolio" : {
                        "price" : null,
                        "quantity" : "24"
                    }
                },
                "options" : {
                    "7" : {
                        "price" : "400",
                        "quantity" : "50000"
                    },
                    "10" : {
                        "price" : "600",
                        "quantity" : "100000"
                    }
                }
      }
    }
  ]
}

2 个答案:

答案 0 :(得分:3)

我提出了一个小的JSBin http://jsbin.com/IdAXuMar/5/edit

好的,所以在聊了聊之后再多看一下,这是我对如何简化这个问题的想法:

您只有一个网址,因此我现在只使用一个路由和一个控制器。

数据模型很简单,因为它是完全分层的:

展示广告有多个商品商品有多个选项

因为您一次只能看一个显示器,所以根本不需要显示器作为模型。如果您的应用程序发展并且您同时拥有多个显示器,则实现Display模型是有意义的,并通过该模型执行所有JSON请求。

我会实现一个路由和控制器:

App.Router.map(function() {
     this.resource('display', path: { 'display/:id' });
});

App.DisplayRoute = Ember.Route.extend({
    model: function(params) {
        return App.Item.find(params._id);
    }
});

DisplayController对其所有项目具有完全访问权限,因为它们被设置为模型。

我认为你现在只需要一个模板,如果它失去控制,你可以将它们分成多个部分。

<script type="text/x-handlebars" data-template-name="display">    
  {{#each model}}
    <!-- access on every item here -->


    {{#each option}}
      {{#if isSelected}}
        this option is selected
      {{/if}}
      <!-- access on every option here -->

      <a {{action selectOption this}} href=''> Select this option</a>

    {{/each}}
  {{/each}}
</script>

注意selectOption操作:当调用它并传递选项时,您可以直接在选项本身上设置选定状态,这将立即反映在视图中。

App.DisplayController = Ember.ArrayController.extend({
    // add computed properties here..

    actions: {
        selectOption: function(option) {
            option.set('isSelected', true);
        }
    }

});

要从服务器获取项目,您可以调用App.Item.find()然后传递显示的ID。这不是100%的常规,因为你可以在这里传递Item的id,但我想为此目的它没关系。所以这个方法看起来像

App.Item = Ember.Option.extend({
    selected: false
    // add computed properties here
});

App.Item.reopenClass({

    // retrieves the items from the server

    find: function(displayId) {

        var url = "/game/json" + displayId;

        var items = new Ember.A();

        Ember.$.getJSON().success(function(data) {
            data.items.forEach(function(jsonItem) {

                var item = Ember.Item.create({
                    nid: jsonItem.nid,
                    title: jsonItem.title,
                    image: jsonItem.image
                });

                item.set('options', new Ember.A());

                jsonItem.options.forEach(function(option) {
                    var option = Ember.Option.create({
                        // set option properties
                    });
                    emberItem.get('options').pushObject(option);
                })

            })

        });

        return items;
    }
});

我希望这可以帮助您入门,也许可以让您更轻松地将您的概念转移到Ember。如果您对如何将所有内容保存回服务器有疑问,请拍摄:)

答案 1 :(得分:2)

以下是答案的开头:

<强>模型

我想我这里只需要三个型号。仪表板是此应用程序中的主要参与者,但它没有任何自己的数据。

  • 商品型号 - 包含商品的所有信息
  • 选项模型 - 包含选项的所有信息
  • 显示模型 - 包含一组选定的选项ID,可以将其发送到服务器&amp;已保存,或可用于将应用程序恢复到特定状态

<强>控制器

早些时候我完全错过了ArrayControllers的概念。通常,任何集合都需要ArrayController来表示它,而不是普通的ember ObjectController。我的“项目”将需要一个,但我不认为“选项”会因为选项是项目的子项,并且可以使用项目/项目作为代理。

  • 仪表板 - 我猜这将是一个强大的,因为控制器需要处理所有项目&amp;集合
  • 项目 - 由于项目很多,我们需要一个ArrayController
  • 项目 - 当项目状态发生变化时,项目需要对其进行简单的分析
  • 选项 - 选项至少需要响应点击操作

<强>模板

此处的缩进表示呈现其他模板的模板。例如,我的展示广告模板包含{{render dashboard}}{{render items}}

  • 应用 - 从技术上讲,应用根,重定向到人机界面(可能没有必要)
    • 显示 - 基本上是我应用的根目录。
      • 信息中心 - 提供项目/选项的可视化分析的区域
      • 项目 - 呈现每个项目
        • 选项 - 呈现每个项目的选项

<强>路线

这仍然很朦胧。路径似乎扮演了很多角色(将URL映射到模型,为控制器设置模型,可能还有其他东西?)。目前我能想到的唯一网址是:

  • 显示 - 由于我的'display'代表应用程序快照(例如,已保存的版本),因此需要在App.Router.map中指定

其他路线:

  • ApplicationRoute
    • setupController:将控制器设置为空白/已保存的显示
  • IndexRoute
    • redirect:只是重定向到显示路径(基本上是应用的根目录)
  • DisplayRoute
    • model:将给定的显示设置为模型
    • afterModel:加载显示
    • 指定的项目

我认为就是这样。这是一个简单的应用程序,一旦我为显示器加载了项目,那么应用程序只会更改屏幕的显示。有用户选择,但它们是布尔标志(例如,在项目上设置isSelected应该改变仪表板显示的数据) - 这些选择不需要任何导航。