如何将嵌套的普通 JavaScript 对象转换为 Ember.js 对象?

6
如果我有一组嵌套的纯JavaScript对象(例如,从JSON返回),如何将它们转换为Ember.js对象(或者至少使绑定功能正常工作)?
例如,如果我有一个像这样的对象:
var x = {
  bar: {
    baz: "quux"
  }
}

然后我将其转换为Ember对象:

var y = Ember.Object.create(x);

如果我设置“baz”的值,它不会更新任何视图,因为它只是一个普通的js对象,而不是Ember对象。

我知道我可以递归地遍历对象键,并一路使用Ember.Object.create,但是否有其他替代方法?

3个回答

2

我不确定您在创建Ember.Object后如何尝试设置baz的值,但是您应该确保使用一个能够被观察者感知的setter函数。对于这个例子,我建议使用setPath()

例如:

var x = {
  bar: {
    baz: "quux"
  }
};
var y = Ember.Object.create(x);
y.setPath('bar.baz', 'foo');

这是一个jsFiddle示例,展示了在设置后视图更新的情况:http://jsfiddle.net/ebryn/kv3cU/


酷,我不知道你可以这样做。我猜它会有点混乱,因为你必须使用两种不同的访问方法。 - Roland
你能详细解释一下你的意思吗? - ebryn
有时候你可以使用标准的js赋值,例如foo.bar = "a",但有时候你需要使用setPath。(我正在使用ENV.USE_ACCESSORS = true,因为我不需要考虑IE)。 - Roland
2
set 现在支持路径。因此不需要使用 setPath - Peter Wagenet

1
这是我的版本:
import { typeOf } from '@ember/utils'
import EmberObject from '@ember/object'

export default function deepEmberObject(anything) {
  if (typeOf(anything) === 'array') {
    return anything.map(a => deepEmberObject(a))
  } else if (typeOf(anything) === 'object') {
    let converted = Object.keys(anything).reduce((acc, k) => {
      acc[k] = deepEmberObject(anything[k])
      return acc
    }, {})
    return EmberObject.create(converted)
  } else {
    return anything
  }
}

测试:

import deepEmberObject from 'zipbooks/utils/deep-ember-object'
import { module, test } from 'qunit'

module('Unit | Utility | deep-ember-object', function() {
  test('it works', function(assert) {
    let result = deepEmberObject({ pandas: [{ id: 3, children: [{ name: 'Bobby', features: { weight: 3 } }] }] })
    assert.equal(
      result
        .get('pandas')[0]
        .get('children')[0]
        .get('features')
        .get('weight'),
      3
    )
  })
})

谢谢你的分享,这非常有帮助。作为对读者的附注,Ember.typeOf将返回EmberObjects的instanceclass。因此,如果您想使用它来深复制ember对象,您应该在else if中以与“object”相同的方式处理这两个值。 https://api.emberjs.com/ember/release/functions/@ember%2Futils/typeOf - fluminis

0

由于某些原因,我不得不独立定义嵌套对象,以确保计算正确工作(即使是枚举的对象也是如此)。

为此,我最终创建了这两个实用函数:

import EmberObject from '@ember/object';
import { A } from '@ember/array';

function fromArrayToEmberArray(array) {
    const emberArray = A();
    array.forEach(function(item) {
        if (Array.isArray(item)) {
            emberArray.push(fromArrayToEmberArray(item));
        } else if (item && typeof item === 'object') {
            emberArray.push(fromObjectToEmberObject(item));
        } else {
            emberArray.push(item);
        }
    });
    return emberArray;
}

function fromObjectToEmberObject(pojo) {
    const emberObject = EmberObject.create();

    for (const key in pojo) {
        const keyObject = pojo[key];
         if (Array.isArray(keyObject)) {
            emberObject.set(key, fromArrayToEmberArray(keyObject))
        } else if (keyObject && typeof keyObject === 'object') {
            emberObject.set(key, fromObjectToEmberObject(keyObject))
        } else {
            emberObject.set(key, keyObject);
        }
    }

    return emberObject;
}

export default {fromObjectToEmberObject};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接