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

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

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.MutableArrayEmber.ObservableEmber.Copyable 这些 mixins 的,其中 Ember.MutableArray才是扩展了 Ember.ArrayEmber.MutableEnumerable mixins 的……

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

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

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

至于为什么?因为 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 是很重要的模式,他们怎么可能不重视。

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