【问题标题】:Getting an arbitrary property from a JavaScript object in Dart从 Dart 中的 JavaScript 对象获取任意属性
【发布时间】:2017-05-07 12:38:42
【问题描述】:

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

如何通过 JsObjectImpl 从 Dart 访问任意 JavaScript 属性?我正在使用 ace.js 库和我从 typescript 接口改编的 Dart 的互操作,并且我调用的方法返回一个带有键值对的普通 javascript 对象。

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

一些错误信息:

  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 对象中没有

    4: Object是我想要的数据。

【问题讨论】:

  • 你能创建一个小例子来演示这个问题吗?如果有需要调试的东西会更容易提供帮助
  • 首选使用dartpad.dartlang.org
  • pub.dartlang.org/packages/js 现在是 dart-js-interop 比 dart:js 更好的选择
  • 仅仅导入另一个包是不够的。阅读软件包的自述文件pub.dartlang.org/packages/js 了解如何使用它。
  • 我会帮助你 - 让我克隆你的包。

标签: javascript dart dart-js-interop


【解决方案1】:

好的,这很有趣,节日快乐:)

看起来Map 不支持package:js 的自动转换。所以有几件事:

  1. 归档https://github.com/dart-lang/sdk/issues/28194
  2. 给你发了PR introducing a workaround

有兴趣的可以使用浏览器原生的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);

【讨论】:

    【解决方案2】:

    我必须修改 @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>();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      相关资源
      最近更新 更多