目录

过去的 JS 互操作

此页面介绍 Dart 中以前版本的 JS 互操作,这些版本被认为是旧的。它们尚未弃用,但将来可能会弃用。因此,建议将来使用dart:js_interop并尽可能迁移旧互操作库的使用。虽然dart:html和其他 Web 库密切相关,但它们在package:web页面中介绍。

dart:js

#

dart:js 公开了与 JS 对象进行互操作的具体[对象包装器]。此包装器包含基于字符串的方法,用于动态获取、设置和调用包装的 JS 对象上的属性。由于包装成本,它的性能较低,并且在人体工程学方面更难使用。例如,您无法获得代码补全,因为您无法声明互操作成员,而是依赖于字符串。 dart:js 中公开的许多功能,如allowInterop,后来通过其他互操作库重新公开。

自从发布 package:jsdart:js_util 以来,该库一直处于旧版状态。它很可能是第一个被弃用的库。

package:js

#

package:js 引入了声明互操作类型和成员的功能。它允许用户编写互操作类而不是互操作扩展类型。在运行时,这些类被擦除为与 dart:js_interopJSObject类似的类型。

dart
@JS()
class JSType {}

package:js 的用户会发现 dart:js_interop 的语法和语义很熟悉。在许多情况下,您可以通过将类定义替换为扩展类型来迁移到 dart:js_interop

但是,存在显著差异:

  • package:js 类型不能用于与浏览器 API 进行互操作。 dart:js_interop 类型可以。
  • package:js 允许动态分派。这意味着,如果您将 package:js 类型强制转换为 dynamic 并调用其上的互操作成员,它将转发到正确的成员。 dart:js_interop 中不再可能这样做。
  • package:js@JS 没有健全性保证,因为未检查 external 成员的返回类型。 dart:js_interop 是健全的。
  • package:js 类型无法重命名实例成员或具有非 external 成员。
  • package:js 类型可以作为非互操作类的子类型和超类型。这通常用于模拟。使用 dart:js_interop ,模拟是通过替换 JS 对象来完成的。参见[模拟教程]。
  • @anonymous 类型是使用对象文字构造函数声明互操作类型的一种方式。 dart:js_interop 不以这种方式区分类型,任何 external 命名参数构造函数都是对象文字构造函数。

@staticInterop

#

除了 @JS@anonymous 之外, package:js 后来公开了@staticInterop,它是互操作扩展类型的原型。它与 dart:js_interop 一样具有表达性和限制性,并且旨在成为一种临时语法,直到扩展类型可用为止。

@staticInterop 类型被隐式擦除为 JSObject 。它要求用户在扩展中声明所有实例成员,以便只能使用静态语义,并且具有更强的健全性保证。用户可以使用它来与浏览器 API 交互,它还允许重命名和非 external 成员等操作。与互操作扩展类型一样,它不支持动态分派。

@staticInterop 类几乎总是可以通过将类更改为扩展类型并删除注释来迁移到互操作扩展类型。

dart:js_interop 公开了 @staticInterop (以及 @anonymous ,但只有在也使用 @staticInterop 时才公开),以支持静态互操作语义,直到扩展类型添加到语言中。所有此类类型现在都应迁移到扩展类型。

dart:js_util

#

dart:js_util 提供了许多无法在 package:js 类型中声明或对于来回传递值是必需的实用程序函数。这包括以下成员:

  • allowInterop (现在是Function.toJS
  • getProperty / setProperty / callMethod / callConstructor (现在位于dart:js_interop_unsafe中)
  • 各种 JS 运算符
  • 类型检查帮助程序
  • 模拟支持
  • 等等。

dart:js_interopdart:js_interop_unsafe 现在包含这些帮助程序,但语法可能有所不同。