Skip to content

Commit

Permalink
Merge branch 'master' of github.com:emberjs-cn/www.emberjs.cn
Browse files Browse the repository at this point in the history
  • Loading branch information
towerhe committed Jul 23, 2014
2 parents fea6d5c + 562cf25 commit 725e6f4
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 108 deletions.
53 changes: 24 additions & 29 deletions source/bilingual_guides/models/index.md

Large diffs are not rendered by default.

66 changes: 22 additions & 44 deletions source/blog/2013-08-31-ember-1-0-released.md
Original file line number Diff line number Diff line change
@@ -1,66 +1,44 @@
---
title: Ember 1.0 Released
author: The Core Team
author: debbbbie
tags: Releases, Recent Posts
---

Today, we're excited to announce the final release of Ember.js 1.0.
怀着激动的心情向大家发布 Ember.js 1.0 最终版。为 Ember.js 第一次提交代码是在 2013 年 4 月 30 号,
距今已经将近两年半。

The first commit to the repository that would become Ember.js happened on April
30th, 2011, almost two and a half years ago.
当时 Backbone.js 发展非常迅速。因为像 SproutCore, Cappuccino, 还有 Dojo 等这些大型类库,
他们都试图从 HTML 中抽象出来,越来越多的开发者反对他们,因为不能做到一个小屋就阅读完源代码。使得“小
型代码库”迅速发展。

At the time, Backbone.js was rocketing to popularity. In response to large
JavaScript frameworks like SproutCore, Cappuccino, and Dojo, which tried to
abstract away HTML, most web developers began rejecting any solution whose
source code they couldn't read over in an afternoon. The "microlibrary" frenzy
had hit full tilt.
浏览器正在变得越来越强大,用户开始需要这种简单的抽象,并不会急剧增大应用的代码规模。

However, we knew that as web browsers became more and more powerful, these
simplistic abstractions wouldn't scale up to the kind of apps that users would
begin to demand.
我们认识到,只要用 HTML 和 CSS 开发出简单好用的工具,开发者们就会抛弃 100% 用 JavaScript 写的网站。

We realized that helping developers grapple with the complexity of building
100% JavaScript web applications could only happen if we embraced the tools
that they were most comfortable with: HTML and CSS.
鉴于目前流行的类库,比如 Ember, Angular 和 Knockout 等,这个策略被证明了是正确的。

Based on the current popularity of frameworks like Ember, Angular and Knockout,
it's clear that this strategy turned out to be the right one.
当我面开始用 Ember.js 开始工作的时候,我们很快的认识到有个很大的问题:仅仅拥有可以绑定到 models
的模板是不够的。我们还需要帮助开发者决定 _哪些_ 模板和 models 应该在要求的时间显示出来。

As we began work on Ember.js, however, we soon realized that there was a
fundamental problem. Just having templates that were bound to models was
not enough. We also needed to help developers decide _which_ templates and
models to display at any given time.
当我们试图找出最好的解决方式,发现好难,不过发现许多 JavaScript 应用都濒临崩溃。
仅仅是因为点了一下浏览器的后退键,就破坏了好多应用,我们还以为这期间有二十年之久。

While struggling to figure out the best solution, we couldn't help but notice
that many JavaScript applications on the web felt broken. Basic things that
we had taken for granted for two decades all of a sudden stopped working.
Just clicking the browser's back button was enough to break many of these apps.
想到解决问题的办法竟然是发现了一个显而易见的真理:决定网站显示什么的是 URL !

We realized that the solution to our problem had been sitting under our noses
all along: the URL is what web applications use to decide what to display!
我们再一次来到小黑板前边,我们重新开始了项目,不再仅仅构建大而且多页的 JavaScript 应用,还尽可能
的不破坏网站的整体结构。

We knew that we had to go back to the drawing board. We rebooted the entire
project mid-course to refocus on how to build JavaScript apps that not only
helped you architect large, multi-page applications, but helped you to do so
without breaking the basic building blocks of the web.
这期间,我们增加了很多新特性,比如组件,用于构建一直的 UI 风格。很高兴看到组织贡献的代码奠定了扎实的基础。

Over time, we've added even more features, like components, that help bring
solid UI architecture to the web. We are incredibly proud of the job that
the community has done to lay a solid foundation that we can build upon for the
years to come.
1.0 最终版履行了我们的承诺:怎样为将来的网站构建一个 JavaScript 类库已经完成。通过 spec 你将会
发现,直到Ember 2.0 都不会有大的修改了。

This 1.0 release is a promise from us: the pain that many experienced while we
were figuring out how to build a JavaScript framework for the future of the web
is now over. In keeping with the Semantic Versioning spec, there will be no
more intentional breaking changes until we release Ember 2.0, which we don't
anticipate happening for some time.

## Recent Developments
## 近期开发内容 Recent Developments

### Router Facelift

Over the past few months, Alex Matchneer has taken the Ember router to the next
level. Alex's changes focus on making the router an excellent tool for managing
在过去的几个月里边, Alex Matchneer 已经将 the Ember router 开发到又一等级。
Alex 的修改 focus on making the router an excellent tool for managing
complex asynchronous flows (like authentication), and you can learn all about it
in his recently completed guides:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
英文原文:[http://emberjs.com/guides/components/sending-actions-from-components-to-your-application/](http://emberjs.com/guides/components/sending-actions-from-components-to-your-application/)

当组件被用于一个模板中时,其可以发送操作给模板的控制器和路由。这样使得组件在一些重要的事件发生时(如一个用户点击了组件中的一个特定的元素,通知应用
当组件被用于一个模板中时,其能够发送操作(action)给模板的控制器和路由。这样可以允许组件在一些重要的事件发生时通知应用。比如一个用户点击了组件中的一个特定的元素,可以触发此操作

就像`{{action}}`Handlebars助手一样,组件发出的操作首先到达模板的控制器。如果控制器没有实现一个操作的处理方法,那么操作会被抛到模板的路由,然后再路由的层级中一路往上冒泡。想知道关于冒泡机制的详细细节,可以查看[操作冒泡](/guides/templates/actions/#toc_action-bubbling)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Todos.Router.map(function () {

</script>

<!-- ... Ember.js 和其他 javascript 依赖库 ... -->
<script src="js/application.js"></script>
<script src="js/router.js"></script>
</body>
Expand Down
4 changes: 2 additions & 2 deletions source/guides/getting-started/deleting-todos.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ actions: {
var todo = this.get('model');
todo.deleteRecord();
todo.save();
},
}
}
},
// ... 为保持代码简洁,在此省略了其他代码 ...
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ remaining: function () {

inflection: function () {
var remaining = this.get('remaining');
return remaining === 1 ? 'item' : 'items';
return remaining === 1 ? 'todo' : 'todos';
}.property('remaining'),
// ... 为保持代码简洁,在此省略了其他代码 ...
```
Expand Down
2 changes: 1 addition & 1 deletion source/guides/getting-started/planning-the-application.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ TodoMVC包含了以下几个主要功能:

1. 使用 `本地存储(localstorage)` 机制保存用户的todos列表,在应用程序启动时重新加载。

你可以通过访问[the TodoMVC site](http://addyosmani.github.com/todomvc/)来体验一下完整的版本。
你可以通过访问[the TodoMVC site](http://todomvc.com/architecture-examples/emberjs/)来体验一下完整的版本。
50 changes: 23 additions & 27 deletions source/guides/models/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,27 @@

## 模型

在Ember中,每个路由都有与之相关联的一个模型。这个模型通过路由的`model`钩子进行设置,可以是通过`{{link-to}}`传入的一个参数,也可以是调用路由的`transitionTo()`方法。
在Ember中,每个路由都有与之相关联的一个模型。这个模型可以通过路由的`model`钩子进行设置,可以通过给`{{link-to}}`传入一个参数,也可以通过调用路由的`transitionTo()`方法。

查看[指定一个路由的模型](/guides/routing/specifying-a-routes-model)可以获取关于设置路由模型的更多信息。

对于简单的应用来说,可以通过jQuery来从服务器加载JSON数据,并将这些数据对象作为模型
对于简单的应用来说,可以通过jQuery来从服务器加载JSON数据,并将这些JSON数据对象作为模型

但是,使用一个模型库来管理查询、更改和将更改保存会服务器,将能大大的简化代码,也能提升应用的健壮性和性能
但是,使用一个模型库来管理查询、更改和将更改保存回服务器,将会大大的简化代码,同时也能提升应用的健壮性和性能

许多Ember应用使用[Ember Data][emberdata]来这里模型。Ember
Data是一个与Ember.js紧密结合在一起,简化了客户端从服务器获取记录,在本地进行缓存,保存修改到服务器,创建新的记录等一系列的操作。
许多Ember应用使用[Ember Data][emberdata]来处理模型。Ember Data是一个与Ember.js紧密结合在一起的代码库,简化了客户端从服务器获取记录,在本地进行缓存以提高性能,保存修改到服务器,创建新的记录等一系列的操作。

Ember Data不需要进行任何配置,就可以实现通过服务端提供的RESTful JSON
API加载和保存记录以及它们的管理关系,这些操作都遵从于特定的惯例。
Ember Data不需要进行任何配置,就可以实现通过服务端提供的RESTful JSON API加载和保存记录以及它们的管理关系,这些操作都遵从于特定的惯例。

如果需要将Ember.js应用与现有的、未遵从惯例的JSON APIs进行集成,Ember
Data也进行了充分的设计,通过简单的配置就可以实现使用服务端返回的数据。
如果需要将Ember.js应用与现有的、未遵从惯例的JSON APIs进行集成,Ember Data也进行了充分的设计,通过简单的配置就可以使用服务端返回的数据。

Ember
Data同样适用于使用基于流的API,例如socket.io、Firebase或WebSockets。通过建立一个与服务器端的Socket连接,在记录发生变化的时候,将这些变更推送到本地仓库中(Store)。
Ember Data同样适用于使用流式的API,例如socket.io、Firebase或WebSockets。通过建立一个与服务器端的Socket连接,在记录发生变化的时候,将这些变更推送到本地仓库中(Store)。

目前,Ember Data还是作为Ember.js的一个独立的库。在Ember Data被作为标准配置的一部分之前,你可以从其[builds.emberjs.com][builds]下载最新的版本。
目前,Ember Data还是一个独立于Ember.js的库。在Ember Data被作为标准发行版的一部分之前,你可以在[builds.emberjs.com][builds]下载最新的版本。

* [Development][development-build]
* [Minified][minified-build]

[emberdata]: https://github.com/emberjs/data
[builds]: http://emberjs.com/builds
[development-build]: http://builds.emberjs.com/canary/ember-data.js
Expand All @@ -38,7 +34,7 @@ Data同样适用于使用基于流的API,例如socket.io、Firebase或WebSocke

#### 仓库

**仓库**是应用用于存放记录的中心仓库。可以认为仓库是应用的所有数据的一个缓存。应用的控制器和路由都可以访问这个共享的仓库;当它们需要显示或者修改一个记录时,首先就需要访问仓库。
**仓库**是应用存放记录的中心仓库。你可以认为仓库是应用的所有数据的缓存。应用的控制器和路由都可以访问这个共享的仓库;当它们需要显示或者修改一个记录时,首先就需要访问仓库。

`DS.Store`的实例会被自动创建,并且该实例被应用中所有的对象所共享。

Expand All @@ -54,7 +50,7 @@ App.IndexRoute = Ember.Route.extend({

#### 模型

**模型**是一个类,它定义了需要呈现给用户的数据的属性和行为。任何用户期望在其离开应用或者回到应用时应该可见的数据,都应该通过一个模型来表示
**模型**是一个类,它定义了需要呈现给用户的数据的属性和行为。任何用户期望在其离开应用然后再回到应用时能够看见的数据,都应该通过模型来表示

例如,如果正在编写一个可以给饭店下单的Web应用,那么这个应用中应该包含`Order``LineItem``MenuItem`这样的模型。

Expand All @@ -73,7 +69,7 @@ App.Person = DS.Model.extend({
});
```

模型也声明了其与其他对象的关系。例如,一个`Order`可以有许多`LineItems`,一个`LineItem`可以属于一个特定的`Order`
模型也声明了它与其他对象的关系。例如,一个`Order`可以有许多`LineItems`,一个`LineItem`可以属于一个特定的`Order`

```js
App.Order = DS.Model.extend({
Expand All @@ -89,7 +85,7 @@ App.LineItem = DS.Model.extend({

#### 记录

**记录**是模型的实例,包含了从服务器端加载而来的数据。应用本身也可以创建新的记录,并将新记录保存到服务器端
**记录**是模型的实例,包含了从服务器端加载而来的数据。应用本身也可以创建新的记录,以及将新记录保存到服务器端

记录由以下两个属性来唯一标识:

Expand All @@ -106,17 +102,17 @@ ID通常是在服务器端第一次创建记录的时候设定的,当然也可

#### 适配器

**适配器**是一个知道特定的服务器后端的对象,主要负责将记录的变更转换为服务器端定义的接口类型,然后发送请求给服务器端
**适配器**是一个了解特定的服务器后端的对象,主要负责将对记录的请求和变更转换为正确的向服务器端的请求调用

例如,如果应用需要一个ID为`1``person`记录,那么Ember Data是如何加载这个对象的呢?是通过HTTP,还是Websocket?如果是通过HTTP,那么URL会是`/person/1`,还是`/resources/people/1`呢?

适配器负责处理类似以上的所有问题。无论何时,当应用需要从仓库中获取一个没有被缓存的记录时,应用就会访问适配器来获取这个记录。如果改变了一个记录并准备保存改变时,仓库会将记录传递给适配器,然后由适配器负责将数据发送给服务器端,并确认保存是否成功。
适配器负责处理所有类似的问题。无论何时,当应用需要从仓库中获取一个没有被缓存的记录时,应用就会访问适配器来获取这个记录。如果改变了一个记录并准备保存改变时,仓库会将记录传递给适配器,然后由适配器负责将数据发送给服务器端,并确认保存是否成功。

#### 序列化

序列化主要负责将服务器端返回的原生JSON数据序列化为记录对象
序列化主要负责将服务器端返回的原生JSON数据转化为记录对象

JSON API可能将属性、关联关系用不同的方式表示。例如,一些属性名可能采用了`驼峰式`命名规则,而另一些又使用了`下划线隔离`的命名规则。关联关系的表示方法更是五花八门:它们有可能会是一个ID数组,一个内嵌的对象集合,也可能是外键
JSON API可能将属性、关联关系用不同的方式表示。例如,一些属性名可能采用了`驼峰式`命名规则,而另一些又使用了`下划线隔离`的命名规则。关联关系的表示方法更是五花八门:它们有可能会是一个ID数组,一个内嵌的对象集合,也可能是作为外键

当适配器从服务器端获取到一个特定记录的数据时,它将数据交给序列化对象,进而将数据转换为Ember Data期望的格式。

Expand All @@ -125,23 +121,23 @@ Data将这些数据作为非透明的对象来处理,它们可能是以二进

#### 自动化缓存

仓库会自动缓存记录。如果一个记录已经被加载了,那么再次访问它的时候,会返回同一个对象实例。这样大大减少了与服务器端的通信,使得应用可以更快的为用户渲染所需的UI。
仓库会自动缓存记录。如果一个记录已经被加载了,那么再次访问它的时候,会返回同一个对象实例。这样大大减少了与服务器端的往返通信,使得应用可以更快的为用户渲染所需的UI。

例如,应用第一次从仓库中获取一个ID为`1``person`记录时,将会从服务器端获取对象的数据。

但是,当应用再次需要ID为`1``person`记录时,仓库会发现这个记录已经获取到了,并且缓存了该记录。那么仓库就不会再向服务器端发送请求去获取记录的数据,而是直接返回第一次时候获取到并构造出来的记录。这个特性使得不论请求这个记录多少次,都会返回同一个记录对象,这也被称为_Identity Map_
但是,当应用再次需要ID为`1``person`记录时,仓库会发现这个记录已经获取到了,并且缓存了该记录。那么仓库就不会再向服务器端发送请求去获取记录的数据,而是直接返回第一次时候获取到并构造出来的记录。这个特性使得不论请求这个记录多少次,都会返回同一个记录对象,这也被称为_Identity Map_(标识符映射)。

使用标识符映射非常重要,因为这样确保了在一个UI上对一个记录的修改会自动传播到UI其他使用到该记录的UI。这样意味着不要手动去保持对象的同步,只需要使用ID来获取应用已经获取到的记录就可以了。
使用标识符映射非常重要,因为这样确保了在一个UI上对一个记录的修改会自动传播到UI其他使用到该记录的UI。同时这意味着你无须手动去保持对象的同步,只需要使用ID来获取应用已经获取到的记录就可以了。

### 架构简介

应用第一次从仓库获取一个记录时,仓库会发现本地缓存并不存在一份被请求的记录的副本,这时会向适配器发请求。适配器将从持久层去获取记录;通常情况下,持久层都是一个HTTP服务,通过该服务可以获取到记录的一个JSON表示。

![未加载记录查询流程图](/images/guides/models/finding-unloaded-record-step1-diagram.png)

如上图所示,适配器有时不能立即返回请求的记录。这时适配器必须向服务器发起一个_异步_的请求,当请求完成加载后,才能通过返回的数据创建请求的记录
如上图所示,适配器有时不能立即返回请求的记录。这时适配器必须向服务器发起一个_异步_的请求,当请求完成加载后,才能通过返回的数据创建的记录

由于存在这样的异步性,仓库会从`find()`方法立即返回一个_承诺_。另外,所有请求需要仓库与适配器发生交互的话,都会返回承诺。
由于存在这样的异步性,仓库会从`find()`方法立即返回一个_承诺_(promise)。另外,所有请求需要仓库与适配器发生交互的话,都会返回承诺。

一旦发给服务器端的请求返回被请求记录的JSON数据时,适配器会履行承诺,并将JSON传递给仓库。

Expand All @@ -157,4 +153,4 @@ Data将这些数据作为非透明的对象来处理,它们可能是以二进

---

以上是理解Ember Data工作原理的核心概念。下面的章节将一个个的深入讨论这些概念,介绍如何将它们串在一起使用。
以上是需要理解的Ember Data工作原理的核心概念。下面的章节将一个个的深入讨论这些概念,介绍如何将它们串在一起使用。
2 changes: 1 addition & 1 deletion source/guides/routing/defining-your-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ App.Router.map(function() {
正如你期望的一样,访问`/`会渲染`index`模板。

访问`/posts`会有点不同。它会先渲染`posts`模板,然后再渲染`posts/index`模板到
`post`模板的出口(`outlet`)上。
`posts`模板的出口(`outlet`)上。

最后,访问`/posts/new`会先渲染`posts`模板,然后渲染`posts/new`模板到它的出口上。

Expand Down
Loading

0 comments on commit 725e6f4

Please sign in to comment.