Kotlin JavaScript模塊
Kotlin 允許你將 Kotlin 項目編譯爲熱門模塊系統的 JavaScript 模塊。以下是
可用選項的列表:
- 無模塊(Plain)。不爲任何模塊系統編譯。像往常一樣,你可以在全局作用域中以其名稱訪問模塊。
默認使用此選項。 - 異步模塊定義(AMD,Asynchronous Module Definition),它尤其爲
require.js 庫所使用。 - CommonJS 約定,廣泛用於 node.js/npm
(require
函數和module.exports
對象) - 統一模塊定義(UMD,Unified Module Definitions),它與 AMD 和 CommonJS 兼容,
並且當在運行時 AMD 和 CommonJS 都不可用時,作爲「plain」使用。
選擇目標模塊系統
選擇目標模塊系統的方式取決於你的構建環境:
在 IntelliJ IDEA 中
設置每個模塊:
打開「File → Project Structure…」,在「Modules」中找到你的模塊並選擇其下的「Kotlin」facet。在
「Module kind」字段中選擇合適的模塊系統。
爲整個項目設置:
打開「File → Settings」,選擇「Build, Execution, Deployment」→「Compiler」→「Kotlin compiler」。 在
「Module kind」字段中選擇合適的模塊系統。
在 Maven 中
要選擇通過 Maven 編譯時的模塊系統,你應該設置 moduleKind
配置屬性,即你的pom.xml
應該看起來像這樣:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
<!-- 插入這些行 -->
<configuration>
<moduleKind>commonjs</moduleKind>
</configuration>
<!-- 插入文本結束 -->
</plugin>
可用值包括:plain
、 amd
、 commonjs
、 umd
。
在 Gradle 中
要選擇通過 Gradle 編譯時的模塊系統,你應該設置 moduleKind
屬性,即
compileKotlin2Js.kotlinOptions.moduleKind = "commonjs"
可用的值類似於 Maven。
[@JsModule](https://github.com/JsModule "@JsModule")
註解
要告訴 Kotlin 一個 external
類、 包、 函數或者屬性是一個 JavaScript 模塊,你可以使用 [@JsModule](https://github.com/JsModule "@JsModule")
註解。考慮你有以下 CommonJS 模塊叫「hello」:
module.exports.sayHello = function(name) { alert("Hello, " + name); }
你應該在 Kotlin 中這樣聲明:
@JsModule("hello")
external fun sayHello(name: String)
將 [@JsModule](https://github.com/JsModule "@JsModule")
應用到包
一些 JavaScript 庫導出包(命名空間)而不是函數和類。
從 JavaScript 角度講 它是一個具有一些成員的對象,這些成員是類、函數和屬性。
將這些包作爲 Kotlin 對象導入通常看起來不自然。
編譯器允許使用以下助記符將導入的 JavaScript 包映射到 Kotlin 包:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
external class C
其中相應的 JavaScript 模塊的聲明如下:
module.exports = {
foo: { /* 此處一些代碼 */ },
C: { /* 此處一些代碼 */ }
}
重要提示:標有 [@file](https://github.com/file "@file"):JsModule
註解的文件無法聲明非外部成員。
下面的示例會產生編譯期錯誤:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
fun bar() = "!" + foo() + "!" // 此處報錯
導入更深的包層次結構
在前文示例中,JavaScript 模塊導出單個包。
但是,一些 JavaScript 庫會從模塊中導出多個包。
Kotlin 也支持這種場景,儘管你必須爲每個導入的包聲明一個新的 .kt
文件。
例如,讓我們的示例更復雜一些:
module.exports = {
mylib: {
pkg1: {
foo: function() { /* 此處一些代碼 */ },
bar: function() { /* 此處一些代碼 */ }
},
pkg2: {
baz: function() { /* 此處一些代碼 */ }
}
}
}
要在 Kotlin 中導入該模塊,你必須編寫兩個 Kotlin 源文件:
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg1")
package extlib.pkg1
external fun foo()
external fun bar()
以及
@file:JsModule("extModule")
@file:JsQualifier("mylib.pkg2")
package extlib.pkg2
external fun baz()
[@JsNonModule](https://github.com/JsNonModule "@JsNonModule")
註解
當一個聲明具有 [@JsModule](https://github.com/JsModule "@JsModule")
、當你並不把它編譯到一個 JavaScript 模塊時,你不能在 Kotlin 代碼中使用它。
通常,開發人員將他們的庫既作爲 JavaScript 模塊也作爲可下載的.js
文件分發,你可以將這些文件複製到
項目的靜態資源,並通過 <script>
元素包含。 要告訴 Kotlin,可以
在非模塊環境中使用一個 [@JsModule](https://github.com/JsModule "@JsModule")
聲明,你應該放置 [@JsNonModule](https://github.com/JsNonModule "@JsNonModule")
聲明。例如,
給定 JavaScript 代碼:
function topLevelSayHello(name) { alert("Hello, " + name); }
if (module && module.exports) {
module.exports = topLevelSayHello;
}
可以這樣描述:
@JsModule("hello")
@JsNonModule
@JsName("topLevelSayHello")
external fun sayHello(name: String)
備註
Kotlin 以 kotlin.js
標準庫作爲單個文件分發,該文件本身被編譯爲 UMD 模塊,因此
你可以使用上述任何模塊系統。也可以在 NPM 上使用 kotlin
包