从Dart中的JavaScript对象获取任意属性

时间:2016-12-21 23:50:55

标签: javascript dart dart-js-interop

修改:Here is a minimal project that illustrates my issue.您可以通过向浏览器提供错误来查看错误:pub get,然后是pub serve(dartium)或pub build --mode=debug(其他浏览器)。

如何通过JsObjectImpl从Dart访问任意JavaScript属性?我正在使用ace.js库和Dart的互操作,我已经从一个打字稿界面改编了,我调用的方法返回一个带有键值对的普通javascript对象。

Dart给了我一个JsObjectImpl,它不能被转换为Map或JsObject,两者都有[]访问器。令人困惑的似乎是从已弃用的JSObject继承而来(注意后者中的大写),它没有[]访问器,因此我无法获取数据。

一些错误消息:

  1. 尝试从JsObjectImpl转换为JsObject时:
    ORIGINAL EXCEPTION: type 'JSObjectImpl' is not a subtype of type 'JsObject' of 'obj' where JSObjectImpl is from dart:js JsObject is from dart:js。我在使用Map时也收到了类似的消息。

  2. 查看调试器中的对象,我可以在JS视图中看到该属性,但Dart对象中的不是Chrome debugger showing a property with the key "4"
    4: Object是我想要的数据。

2 个答案:

答案 0 :(得分:4)

好的,这是一个有趣的,节日快乐:)

Map似乎不支持package:js自动转换。所以有几件事情:

  1. 提起https://github.com/dart-lang/sdk/issues/28194
  2. 发送了您的PR introducing a workaround
  3. 对于感兴趣的各方,我们可以使用浏览器原生的Object.keys

    @JS()
    library example;
    
    import 'package:js/js.dart';
    
    /// A workaround to converting an object from JS to a Dart Map.
    Map jsToMap(jsObject) {
      return new Map.fromIterable(
        _getKeysOfObject(jsObject),
        value: (key) => getProperty(jsObject, key),
      );
    }
    
    // Both of these interfaces exist to call `Object.keys` from Dart.
    //
    // But you don't use them directly. Just see `jsToMap`.
    @JS('Object.keys')
    external List<String> _getKeysOfObject(jsObject);
    

    一旦我们有一个任意的JavaScript对象,就调用它:

    var properties = jsToMap(toy.getData());
    print(properties);
    

答案 1 :(得分:0)

我不得不修改@matanlurey解决方案,以便它可以在dart 2.12上运行并且是递归的。

import 'dart:js';

/// A workaround to deep-converting an object from JS to a Dart Object.
Object jsToDart(jsObject) {
  if (jsObject is JsArray || jsObject is Iterable) {
    return jsObject.map(jsToDart).toList();
  }
  if (jsObject is JsObject) {
    return Map.fromIterable(
      getObjectKeys(jsObject),
      value: (key) => jsToDart(jsObject[key]),
    );
  }
  return jsObject;
}

List<String> getObjectKeys(JsObject object) => context['Object']
    .callMethod('getOwnPropertyNames', [object])
    .toList()
    .cast<String>();