Kotlin 允許你將 Kotlin 項(xiàng)目編譯為熱門(mén)模塊系統(tǒng)的 JavaScript 模塊。以下是
可用選項(xiàng)的列表:
require 函數(shù)和 module.exports 對(duì)象)選擇目標(biāo)模塊系統(tǒng)的方式取決于你的構(gòu)建環(huán)境:
設(shè)置每個(gè)模塊:
打開(kāi)“File → Project Structure…”,在“Modules”中找到你的模塊并選擇其下的“Kotlin”facet。在
“Module kind”字段中選擇合適的模塊系統(tǒng)。
為整個(gè)項(xiàng)目設(shè)置:
打開(kāi)“File → Settings”,選擇“Build, Execution, Deployment”→“Compiler”→“Kotlin compiler”。 在
“Module kind”字段中選擇合適的模塊系統(tǒng)。
要選擇通過(guò) Maven 編譯時(shí)的模塊系統(tǒng),你應(yīng)該設(shè)置 moduleKind 配置屬性,即你的pom.xml 應(yīng)該看起來(lái)像這樣:
<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>
<!-- 插入文本結(jié)束 -->
</plugin>
可用值包括:plain、 amd、 commonjs、 umd。
要選擇通過(guò) Gradle 編譯時(shí)的模塊系統(tǒng),你應(yīng)該設(shè)置 moduleKind 屬性,即
compileKotlin2Js.kotlinOptions.moduleKind = "commonjs"
可用的值類(lèi)似于 Maven。
@JsModule 注解要告訴 Kotlin 一個(gè) external 類(lèi)、 包、 函數(shù)或者屬性是一個(gè) JavaScript 模塊,你可以使用 @JsModule
注解??紤]你有以下 CommonJS 模塊叫“hello”:
module.exports.sayHello = function(name) { alert("Hello, " + name); }
你應(yīng)該在 Kotlin 中這樣聲明:
@JsModule("hello")
external fun sayHello(name: String)
@JsModule 應(yīng)用到包一些 JavaScript 庫(kù)導(dǎo)出包(命名空間)而不是函數(shù)和類(lèi)。
從 JavaScript 角度講 它是一個(gè)具有一些成員的對(duì)象,這些成員是類(lèi)、函數(shù)和屬性。
將這些包作為 Kotlin 對(duì)象導(dǎo)入通??雌饋?lái)不自然。
編譯器允許使用以下助記符將導(dǎo)入的 JavaScript 包映射到 Kotlin 包:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
external class C
其中相應(yīng)的 JavaScript 模塊的聲明如下:
module.exports = {
foo: { /* 此處一些代碼 */ },
C: { /* 此處一些代碼 */ }
}
重要提示:標(biāo)有 @file:JsModule 注解的文件無(wú)法聲明非外部成員。
下面的示例會(huì)產(chǎn)生編譯期錯(cuò)誤:
@file:JsModule("extModule")
package ext.jspackage.name
external fun foo()
fun bar() = "!" + foo() + "!" // 此處報(bào)錯(cuò)
在前文示例中,JavaScript 模塊導(dǎo)出單個(gè)包。
但是,一些 JavaScript 庫(kù)會(huì)從模塊中導(dǎo)出多個(gè)包。
Kotlin 也支持這種場(chǎng)景,盡管你必須為每個(gè)導(dǎo)入的包聲明一個(gè)新的 .kt 文件。
例如,讓我們的示例更復(fù)雜一些:
module.exports = {
mylib: {
pkg1: {
foo: function() { /* 此處一些代碼 */ },
bar: function() { /* 此處一些代碼 */ }
},
pkg2: {
baz: function() { /* 此處一些代碼 */ }
}
}
}
要在 Kotlin 中導(dǎo)入該模塊,你必須編寫(xiě)兩個(gè) 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 注解當(dāng)一個(gè)聲明具有 @JsModule、當(dāng)你并不把它編譯到一個(gè) JavaScript 模塊時(shí),你不能在 Kotlin 代碼中使用它。
通常,開(kāi)發(fā)人員將他們的庫(kù)既作為 JavaScript 模塊也作為可下載的.js 文件分發(fā),你可以將這些文件復(fù)制到
項(xiàng)目的靜態(tài)資源,并通過(guò) <script> 元素包含。 要告訴 Kotlin,可以
在非模塊環(huán)境中使用一個(gè) @JsModule 聲明,你應(yīng)該放置 @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 標(biāo)準(zhǔn)庫(kù)作為單個(gè)文件分發(fā),該文件本身被編譯為 UMD 模塊,因此
你可以使用上述任何模塊系統(tǒng)。也可以在 NPM 上使用 kotlin 包