没有 Ember 数据的 Ember

Posted

技术标签:

【中文标题】没有 Ember 数据的 Ember【英文标题】:Ember without Ember Data 【发布时间】:2014-08-16 00:42:37 【问题描述】:

Ember 数据仍然不是 1.0 版,因此我决定使用没有数据模型的 Ember。

我有自己的模型,它们是由路由模型函数创建的。

然而,维护前端对象和后端对象之间的状态是一场噩梦。 尤其是当一条路线使用另一条路线模型时。

如何实现,我应该编写自己的商店和模型查找方法吗? 我是否应该使用 Ember Data(即使它不是 1.0 版?)或者 Ember Data 1.0 上的 ETA? 每次更改模型时都要编写代码来更新前端的模型? 另一种方法?

我正在做的事情是最佳做法还是应该以不同的方式做? 我的直觉是,如果不使用 Ember Data,我应该编写自己的商店。我很想得到你们中的一些人的反馈。

模型示例:

App.Person = Ember.Object.extend(App.Serializable,Em.Copyable,
  user_email : null //used in routing dynamic segements and as old email when making changes to email
  ,first_name: null
  , last_name: null
  , fullname : function () 
    return this.first_name + ' ' + this.last_name;
  .property('first_name','last_name').cacheable()
;

App.Person.reopenClass(
  createRecord: function(data) 
    return App.Person.create(
      user_email : data.email
      , first_name: data.first_name
      , last_name : data.last_name
);

我如何加载类模型的示例:

App.UsersRoute = App.AuthenticatedRoute.extend( 
  model : function () 
    return new Ember.RSVP.Promise(function(resolve, reject) 
      $.getJSON('/users').then(function(usersData) 
        var userObjects = [];
          usersData.forEach(function (data) 
            userObjects.pushObject(App.Person.createRecord(data));
          );
        resolve( userObjects);
        ,function(error) 
          reject(error);
      );
    )
  ,

子路由使用模型:

App.UsersAvailableRoute = App.AuthenticatedRoute.extend( 
     model : function () 
        return 
          allUsers :  Ember.ArrayController.create(
            content : this.modelFor('users').filter( function (user) 
                      return user.availablity === 100
                      ),

我如何在控制器中更新模型的示例:

App.UsersAvailableController = Ember.ArrayController.extend(
needs : ['users']
    ,applyPersonAssign : function (person,need,project) 
          need.set('allocated',person);
          var updateObject = Ember.copy(project,true);
          if (Ember.isEmpty(need.get('inProject'))) 
            updateObject.projectNeeds.pushObject(need);
          

          return $.ajax(
            url: '/projects/' + updateObject.get('codename'),
            "type": "PUT",
            "dataType": "json",
            data: updateObject.serialize()
          )

【问题讨论】:

【参考方案1】:

您不一定需要重新创建 Ember 数据存储。 Ember 与 POJO 配合得很好,您还可以将 POJO 包装在 Ember 对象中,为您提供一些有趣的内置功能。

也就是说,创建一个缓存结果的自定义适配器可能很方便。

这是我创建支持缓存的适配器的示例。您可以在概念的基础上慢慢构建您需要的所有基本内容。

App.FooAdapter = Ember.Object.extend(
  cache:,
  find: function(id)
    var self = this,
        record;
    if(record = this.cache[id])
      return Ember.RSVP.cast(record);
    
    else
    
      return new Ember.RSVP.Promise(function(resolve)
        resolve($.getJSON('http://www.foolandia.com/foooo/' + id));
      ).then(function(result)
        record = self.cache[id] = App.Foo.create(result);
        return record;
      );
    
  
);

在下面的示例中,我使用容器在我的所有路由/控制器上注册适配器,因此我可以轻松访问它。

http://emberjs.jsbin.com/OxIDiVU/742/edit

如果你总是希望它成为一个承诺:

http://emberjs.jsbin.com/OxIDiVU/740/edit

可重用性

上面的例子可能会让你看起来需要做大量的工作,但不要忘记,Ember 是超级可重复使用的,利用它的魔力。

App.MyRestAdapter = Em.Object.extend(
  type: undefined,
  find: function(id)
    $.getJSON('http://www.foolandia.com/' + this.get('type') + '/' + id
  
);

App.FooAdapter = App.MyRestAdapter.extend(
  type: 'foo' // this would create calls to: http://www.foolandia.com/foo/1
);

App.BarAdapter = App.MyRestAdapter.extend(
  type: 'bar' // this would create calls to: http://www.foolandia.com/bar/1
);

这是 Ember 数据/Ember 模型的基本概念。他们试图创建大量默认值并内置酷炫,但有时这太过分了,特别是如果您只是使用数据而不进行 CRUD。

例如:http://emberjs.jsbin.com/OxIDiVU/744/edit

你也可以阅读这个(说同样的话):

How do you create a custom adapter for ember.js?

【讨论】:

只是为了确认这行得通....我们非常广泛地使用这种方法,成功地拥有复杂的对象图和各种疯狂的网络服务:) 或者您也可以按照本指南eviltrout.com/2013/03/23/ember-without-data.html @fanta 谢谢,我看到了那篇文章,但它使用了 ES6 模块(我没有使用它,它使用了我不使用的 ember cli :).. @kingpin2k 如果您已经找到了单个元素,您如何将其与 FindAll 一起使用?您是否进行迭代以确保不会两次加载同一个对象? 我从另一段代码中复制了这个,我期望 RSVP.Promise 的一些功能(最后还是什么,我不记得了)。真的,我会为正确的工作选择正确的工具,Ember Data 让简单的事情变得简单,而让困难的事情变得非常困难(在目前的状态下)。如果您对编程感到自在,那么使用自己的编程并没有那么大的飞跃,并且可以根据您的需要轻松定制。对于 jquery 已经提供的出色 XHR 功能尤其如此(无论如何它都在您的应用程序中)。【参考方案2】:

在我工作的地方,我们使用的是 Ember Data 和 Ember CLI,尽管它们相当不稳定。到目前为止,Ember Data 并没有给这里带来太多的痛苦和折磨。商店很容易理解,而且 Ember 上关于框架这方面的文档也相当不错。我遇到的一个问题与动态排序模型有关,当我修改它们的内容时,它们会根据我所做的更改重新洗牌,并且在路上的某个地方发生了一些非常奇怪的事情,不确定那是不是 Ember虽然是数据的错。

简而言之,我们在使用 Ember Data 方面取得了一些成功,如果这就是您想要走的路,我们不能抱怨。

【讨论】:

【参考方案3】:

如果您熟悉 Ruby,Rails 是一个很好的后端解决方案。

ember 社区通过 ember-rails gem 支持 rails,这使您可以使用 rails 作为服务 JSON 的一种方式。

开始

将 gem 添加到您的应用程序 Gemfile:

gem 'ember-rails' gem 'ember-source', '~> 1.9.0' # 或者你需要的版本

运行bundle install

接下来,生成应用结构:

rails 生成 ember:bootstrap

重新启动您的服务器(如果它正在运行)

从头开始构建一个新项目

Rails 支持从模板源 ruby​​ 文件构建项目的能力。

要构建一个以 Ember 为中心的 Rails 项目,您只需在命令行中输入以下内容:

rails new my_app -m http://emberjs.com/edge_template.rb

安装最新版本的 ember 和 ember-data。应该指出的是, getting started guide 中的示例 已被设计为使用 ember 的已发布版本:

rails generate ember:install

然后你需要做的就是在你的控制器中渲染 json,像这样

class ProjectsController < ApplicationController
    def index
        respond_to do |format|
            format.json  render json: Project.all 
        end
    end

    def show
        respond_to do |format|
            format.json  render json: Project.where(name: params[:name])
        end
    end
end

确保更新您的序列化程序

class ProjectSerializer < ApplicationSerializer
  attributes :id, :name, :description, :imgUrl, :deployUrl
end 

设置你的路线

EmberRailsBlog.ProjectsRoute = Ember.Route.extend(
    model: function()
        return this.store.find('project');
    
);

最后是你的模型

var attr = DS.attr;

EmberRailsBlog.Project = DS.Model.extend(
    name: attr(),
    description: attr(),
    imgUrl: attr(),
    deployUrl: attr()
);

【讨论】:

以上是关于没有 Ember 数据的 Ember的主要内容,如果未能解决你的问题,请参考以下文章

Ember.Select 使用 belongsTo Ember 数据模型属性的默认选择值?

为啥没有调用我的 ember.js 路由模型?

Ember 验收测试没有看到更新的 DOM

没有服务器的Ember Js App

生产环境中没有节点的 Ember.js 预编译器

ember.js 和服务器