Javascript 在开始使用Ember.js时,Rails或服务器端开发人员在思维上应该做出什么样的转变?
虽然我最近的大部分工作主要是使用RubyonRails和大量Javascript(主要是jQuery),但我想构建一个单页应用程序,并认识到Ember.js似乎是一个新兴的流行框架,可以用来处理此类应用程序 从各种文档和教程来源来看,Ember.js似乎需要一种与RubyonRails或其他典型服务器端框架截然不同的思考方式来解决问题。随着时间的推移,使用Ruby on Rails等框架开发的关于“事情应该如何运作”的某些假设似乎可能会妨碍人们真正理解和接受“余烬方式” 在尝试学习Ember时,RubyonRails开发人员需要消除哪些先入为主的观念?RubyonRails开发人员应该考虑的最具创新性和最重要的Ember概念是什么Javascript 在开始使用Ember.js时,Rails或服务器端开发人员在思维上应该做出什么样的转变?,javascript,ruby-on-rails,model-view-controller,ember.js,Javascript,Ruby On Rails,Model View Controller,Ember.js,虽然我最近的大部分工作主要是使用RubyonRails和大量Javascript(主要是jQuery),但我想构建一个单页应用程序,并认识到Ember.js似乎是一个新兴的流行框架,可以用来处理此类应用程序 从各种文档和教程来源来看,Ember.js似乎需要一种与RubyonRails或其他典型服务器端框架截然不同的思考方式来解决问题。随着时间的推移,使用Ruby on Rails等框架开发的关于“事情应该如何运作”的某些假设似乎可能会妨碍人们真正理解和接受“余烬方式” 在尝试学习Ember时,
提前谢谢 我将以StackOverflow的精神尽我所能回答这个问题,列出Ember和Rails之间的一些主要技术差异。我会把更哲学的一面留给那边的其他人 您可以在一个if中找到下面的所有代码示例,这有助于您可视化所有内容是如何组合在一起的 集合和对象的单独路由 Ember和Rails之间的一个主要区别是收集路由(管理对象列表)和项目路由(管理单个对象)之间的关系。在Rails中,这两个都由单个资源控制器处理。在Ember中,它们通常由两个单独的路由处理,因为它们操作两种不同的数据结构:
App.Router.map(function () {
this.route("posts", { path: "posts" });
this.route("post", { path: "post/:post_id" });
});
App.PostsRoute = Ember.Route.extend({
model: function (params) {
return App.Post.find();
}
});
App.PostRoute = Ember.Route.extend({
model: function (params) {
return App.Post.find(params.post_id);
}
});
路由与控制器、视图与模板
在Rails中,代码分为三大类:
- 模型:数据库行上的面向对象抽象
- 视图:可由控制器呈现的模板
- 控制器:接受HTTP请求、加载和操作模型、渲染视图
App.Post = DS.Model.extend({
title: DS.attr("string"),
body: DS.attr("string"),
comments: DS.hasMany("App.Comment")
});
路由。路由表示应用程序中用户可见的位置,它们对应于URL,如/post/7
或/about
。正如您在上面的代码示例中所看到的,路由在Ember中做得更多。最重要的是,他们查找与给定URL对应的模型。他们还负责连接适当的控制器和视图,稍后您将看到
控制器。控制器与Rails完全不同!关于Ember控制器,需要了解的两件最重要的事情是:(1)它们基本上是模型对象周围的智能代理,(2)它们通常是单例。因此,您只有一个PostController
,它将连接到您现在正在查看的任何帖子
一般来说,您可以使用余烬控制器来管理不属于URL或数据库的瞬态。下面是一个例子:
App.PostController = Ember.ObjectController.extend({
// This shared between all posts for as long as the app runs (because
// this controller is a singleton), but it doesn't get saved in the database
// (because this is a controller, not a model).
lowRatedCommentsShown: false,
// Called by PostView or its template in response to an HTML event.
showLowRatedComments: function () {
this.set("lowRatedCommentsShown", true);
},
// Called by PostView or its template in response to an HTML event.
hideLowRatedComments: function () {
this.set("lowRatedCommentsShown", false);
}
});
因为余烬控制器是模型的代理,它们也倾向于积累几乎属于模型的逻辑,但感觉与应用程序中的特定屏幕联系太紧密
视图和模板。余烬视图和模板协同工作。最好将它们看作GUI小部件
App.PostView = Ember.View.extend({
// This can be omitted when we're created by a route.
templateName: 'post'
// Any HTML event handlers would go here if we needed them. Our job is to
// map between HTML events and events understood by the controller.
//doubleClick: function (evt) {
// // We'll actually bind this to a specific button, not a click event.
// this.get("controller").send("showLowRatedComments");
//}
});
我们的post模板自由混合了模型定义的字段和控制器定义的字段:
<script type="text/x-handlebars" data-template-name="post">
<h2>{{title}}</h2>
<div class="body">{{body}}</div>
{{#if lowRatedCommentsShown}}
<button {{action 'hideLowRatedComments'}}>Hide Low-Rated Comments</button>
{{else}}
<button {{action 'showLowRatedComments'}}>Show Low-Rated Comments</button>
{{/if}}
{{partial "comments"}}
</script>
当服务器向您发送数据时,您将看到:
post.get("isLoaded"); // -> true
post.get("title"); // -> "Post #1"
为了让这一切变得无痛,余烬严重依赖于,和。在每一种情况下,关键思想是数据的更改应该自动在系统中传播。例如,我们可以使用computed属性来确保注释的评级
在任何时候更改时更新IsLowlated
:
App.Comment = DS.Model.extend({
post: DS.belongsTo("App.Post"),
body: DS.attr("string"),
rating: DS.attr("number"),
isLowRated: function () {
return this.get("rating") < 2;
}.property("rating") // A list of properties we depend on.
});
实际上,Ember感觉比Rails异步得多,但比Node.js这样的事件系统异步得少。这是因为大多数异步更新都是由绑定自动管理的
余烬数据
这是一个地方,我将偏离严格的技术细节,并提到一些实用的建议。余烬数据提供了如上所示的DS.Model。它不是Ember.js-check-out的唯一模型层,也不是用于替代的类似库。目前,还没有官方发布的余烬数据,但如果你想生活在最前沿,在生产应用程序中可以非常谨慎地使用它。一些提示:
hasMany
关系序列化一个完整的ID列表。看看你是否在使用Rails使用余烬数据可以得到非常好的结果。但它远不如ActiveModel成熟,需要这样对待。虽然我认为这是一个令人敬畏的问题,但我相信它更适合@ChristopherMarshall所说的事实。但我也对这个问题进行了投票并将其添加到书签中,因为我对答案感兴趣:)stackoverflow是目前所有stackexchange网站中最活跃的一个。+1感谢您出色而详细的回复。非常感谢你!没问题!关于Ember控制器还有一个想法:它们实际上与一些人在Rails中使用“presenters”的方式有很多共同点,作为一种合作伙伴
App.Comment = DS.Model.extend({
post: DS.belongsTo("App.Post"),
body: DS.attr("string"),
rating: DS.attr("number"),
isLowRated: function () {
return this.get("rating") < 2;
}.property("rating") // A list of properties we depend on.
});
Ember.run(function () {
// Change some bindings here. Not all changes will propagate immediately.
});
// Test that the values have all propagated here, after the run loop is done.