Ember.get() 和 this.get() 的区别

Posted

技术标签:

【中文标题】Ember.get() 和 this.get() 的区别【英文标题】:Difference between Ember.get() and this.get() 【发布时间】:2017-03-29 03:47:06 【问题描述】:

我是 Ember 的新手,我一直对 this.get()Ember.get() 之间的区别感到困惑。谁能简单解释一下?

【问题讨论】:

【参考方案1】:

欢迎来到 Ember ;-)

每个扩展 Ember Observable mixin 的对象都支持 get() 方法(等等)。

当您调用this.get() 时,this 必须引用这样的对象(Route、Controller、Component、您自己的扩展 Ember.Object 的类等)。在普通对象上调用 get() 会导致失败。让我来看看区别:

const emberObjectInstance = Ember.Object.create(
 name: 'Bala'
);

emberObjectInstance.get('name'); // returns 'Bala'

const plainObject =  name: 'Bala';
plainObject.get('name'); // causes a failure since get() is not a function

但是,在这两种情况下都使用Ember.get() 成功:

Ember.get(emberObjectInstance, 'name'); // returns 'Bala'
Ember.get(plainObject, 'name');         // returns 'Bala', too

也可以用import写成如下

import  get  from '@ember/object';

get(emberObjectInstance, 'name'); // returns 'Bala'
get(plainObject, 'name');         // returns 'Bala', too

注意:不要忘记,调用 get() 中的任何一个都会使计算属性得到计算(在最常见的情况下,我现在不想深入研究 - 惰性计算、易失性扩展等),但为了了解其中的区别,我们可以使用简单的值。

根据自己的经验,我在任何我知道普通对象可能是我需要检索其属性的对象的地方都使用Ember.get()。一个很好的例子是 setupController() 钩子,我可以将单元测试中的普通对象传递到该钩子中,以测试 setupController() 的功能。

// some route:
setupController(controller, model)
    this._super(...arguments);

    const name = Ember.get(model, 'name'); // ***

    controller.set('isNamePresentOnSetup', Ember.isPresent(name));


// in my unit tests I can use plain object:
...
const modelMock =  name: 'Bala' ; // plain object is enough because I use Ember.get instead of model.get() (see ***)?
const controllerMock = Ember.Object.create(); // has to be Ember.Object since I use controller.set() within setupController()

subject.setupController(controllerMock, modelMock);
assert.ok(controllerMock.get('isNamePresentOnSetup'), "property 'isNamePresentOnSetup' set up correctly if model name is present");
...

我也可以使用Ember.set(controller, 'isNamePresentOnSetup', Ember.isPresent(name)),然后将普通控制器模拟传递给setupController()

我认为这是一个好的开始,因为您是 Ember 的新手,我相信 Ember 专家还有很多要补充的。 相关 Ember 文档:

https://guides.emberjs.com/v2.9.0/object-model/

https://guides.emberjs.com/v2.9.0/object-model/computed-properties/

https://guides.emberjs.com/v2.9.0/object-model/reopening-classes-and-instances/

更新:get() 与chained paths 一起使用与使用POJO 不同。 例如在objectInstance.get('a.b.c') 中,如果bundefined,则返回值为undefined。当 b 为 undefined 时将其转换为 objectInstance.a.b.c 会引发异常。

【讨论】:

感谢您的简要解释。 我认为解释有误。在“const modelMock = name: 'Bala'; // 普通对象就足够了,因为我使用 Ember.set 而不是 model.set(),你明白吗?” ,其实就是 Ember.get() ryt??【参考方案2】:

没有。 foo.get('bar') 等价于 Ember.get(foo, 'bar')。但是因为 foo.get 是在 Ember.Object 上定义的,所以您只能在 Ember 对象上调用 .get()Ember.get() 将适用于所有 ember 对象。在 Ember 对象上,Ember.get(foo, 'bar') 等效于 foo.get('bar'),在所有其他对象上,它等效于 foo['bar']

【讨论】:

谢谢你的回答:)【参考方案3】:

请注意,如果运行于 2018 年 4 月发布的 Ember >= 3.1,则大多数用例不再需要使用 Ember.get()this.get()。您现在可以使用原生 ES5 getter。可以在release notes for Ember 3.1 中找到有关此更改的快速介绍。在RFC 281 中有更详细的讨论。

有一个代码模式可以帮助您过渡到 ES5 getter:es5-getter-ember-codemod 它可以作为ember-cli-update 的一部分运行。

请注意,不推荐使用 Ember.get()this.get()。上面链接的发行说明中列出的某些边缘情况仍然需要它:

实际上有几种情况你还是必须使用get:

如果您使用链式路径调用 get。例如在 this.get('a.b.c') 中,如果 b 未定义,则返回值未定义。当 b 未定义时,将 this 转换为 this.a.b.c 会引发异常。 如果您的对象正在使用 unknownProperty,您必须继续使用 get。在具有 unknownProperty 的对象上使用 ES5 getter 会导致开发中的断言失败。 当您从其他 API 读取异步关系时,Ember Data 返回 Promise 代理对象。 Ember 代理对象(包括 Promise 代理)仍需要您调用 get 来读取值。

请注意,如果使用ember-changeset,则存在特殊情况。它提供了自己的.get() 实现。因此,如果thisember-changeset,则Ember.get(this, 'value')this.get('value') 具有不同的结果。您可以在documentation of ember-changeset 中找到有关该案例的更多信息。

【讨论】:

以上是关于Ember.get() 和 this.get() 的区别的主要内容,如果未能解决你的问题,请参考以下文章

检查Ember.js:获取对象的类型(Class)?

在android中使用“by viewModels()”与“ViewModelProvider(this).get(ViewModel::class.java)”进行视图模型初始化

dorado7常用内容

Vue中的观察者与发布订阅

get([index])

[ jquery 方法 get(index) ] 可以将取得的相应jquery对象和DOM元素对象进行转化