新手问题 有句话怎么也看不明白,谁能帮翻译下

hxygsh · 2016年05月05日 · 最后由 nightire 回复于 2016年05月05日 · 3108 次阅读

When you provide a model in themodelhook of a route ember converts the raw array (users) into an ember array that provides observation and convenience methods likepushObject.

是针对这行代码的解释: var user = users.pushObject({id: users.length}); //创建一个新用户

完整代码段:

App.ApplicationRoute = Ember.Route.extend({
  model: function() {
    return users;
  },

  events: {
    createUser: function() {
      var users = this.modelFor('application');    // 定义数据来源于 application 数据模型     
      var user = users.pushObject({id: users.length});   //创建一个新用户
      this.transitionTo('editUser', user);    // 转向 editUser 页面
    }
  }
});

先把翻译给你:

当你为路由的 model 钩子提供了一个模型的时候,Ember 会把原始数组(users)转换为 ember array(这里最好能加上 Ember.Array 的 API 链接),(和原始数组相比)ember array 提供了 observation 以及诸如 pushObject 这样的便利方法。


以上是字面的翻译,里面有我附加的一些解释,可以自行斟酌处理。

稍微说点背景,JavaScript 语言所提供的原生集合类型(数组、对象等)都是很“单纯”的,你可以理解为最小化实现,只提供最基本的功能。但是做一个 UI 框架需要更多东西,所以就会去扩展这些原生集合类型,Ember.Array 就是这样一个代表,你可以把任意一个原生数组转变为 Ember.Array 而不损失任何原生特性,并且能够获得很多新的特性,比如上文提到的 observation 能力和 pushObject 方法等等。

因为在 Ember 的架构中这些“扩展”能力发挥着非常重要的作用,因此在很多地方 Ember 都会为你做隐式数据结构转换。上文说的就是比较重要的一个地方:路由的 model 钩子。如果此方法返回的是一个原生数组,那么为了确保接下来视图层获取的模型具有诸如 observation 等等必要的特性,Ember 会在这里隐式转换其为 Ember.Array 类型。

我不清楚这是早就有的隐式类型转换还是最近才加的,因为以前我都是习惯手动转换的:Ember.Array([]) 或是用了 Ember Data 的话由 Data 层来负责处理这件事情,这个可以去看一下 model hook 的源码历史记录。Anyway,自动的转换是好事,因为对于初学者来说不需要预先了解 Ember.Array,在他看来数组就是数组并没有什么区别,只不过他也就错过了 Ember.Array 所提供的进阶能力,那么将来他会觉得这里面似乎有一些“黑魔法”是他在“野生”JavaScript 世界里所不曾遇见过的。


再补充一点进阶的,Ember.Array 其实是一个 mixin,真正常用的 High Level APIs 并不是它,而是 Ember.NativeArray,而 NativeArray 又是扩展了 Ember.MutableArray,Ember.Observable,Ember.Copyable 这些 mixins 的,其中 Ember.MutableArray才是扩展了 Ember.Array 和 Ember.MutableEnumerable mixins 的……

这个对象树关系是很长,就跟我们学 Ruby 的对象关系树类似,但作为高阶框架的使用者,我们很少会直接去触碰这些相对低层的部分。拿 Ember 来说,集合类型如果直接处理原生的,那么 Ember 会在一些关键地方提供隐式转换,所以等到你在视图层(组件)真正使用它们的时候,它们都是“升级”过的——除非你就不按框架的约定来,这也是“约定”的体现之一;如果不直接处理原生集合,而是使用了 Ember Data 这样的高度抽象数据层,那么 Ember Data 自身就是由上述那些个基本类型和 mixins 组合而成,所以得到的结果也是一样的。

@nightire 非常感谢您专业的回复,学习到不少知识,得好好消化一下,谢谢!

补充几点。Ember 默认对 Array, String, Function 的 prototype 做了部分扩展来添加一些方法,你说的 pushObject 就是这类。常见的还有 Function 的 on , property 和 observes 。这个特性也可以关掉,具体见 这里 。

至于为什么?因为 Ember 的双向绑定机制是 KVO (Key Value Observer) 。它通过给对象加 observer 来通知页面更新(和做双向绑定链)。但 JavaScript 原生的对象没有这种功能。所以常用对象都要用 Ember 提供的类封装一下,这也是为什么必须使用 get/set 来更新属性的原因。如果 ES 的 Object.observable 没有被废弃的话,Ember 会是最大的受益者。不过现在公认看好的解决方案是 virtual dom,所以……

#3 楼 @darkbaby123 Object.observe() 被废弃了,但是 Observable 没有。实际上是因为后者才导致前者被废弃的(很重要的一个原因),后者明显是更好的方案。

@nightire 啊对,我记错了。名字太相似了。这是不是跟 Rx.js 很像?

#5 楼 @darkbaby123 对呀,Object.observe() 是很狭隘没有远见的想法,所以被废弃是很正常的,当时还有一些人在幸灾乐祸呢,但 TC39 的人也不是傻子,对 UI 编程来说 Observable 是很重要的模式,他们怎么可能不重视。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号