內容

過往的 JS 互通

此頁面說明 Dart 中先前版本的 JS 互操作,這些版本被視為舊版。它們尚未棄用,但未來可能會棄用。因此,建議優先使用 dart:js_interop,並在可能的情況下將舊版互操作函式庫的用法遷移。儘管 dart:html 和其他網路函式庫密切相關,但它們在 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 現在包含這些輔助程式,但語法可能不同。