我最後一次使用科特林是2015年12月,當我把它用來solve a couple of Project Euler problems.使用JavaScript庫在科特林
這一次我想嘗試它使用JavaScript的互操作性。現在我的問題是,我們如何在Kotlin中導入/使用現有的Javascript庫? 我見過一些人使用native
關鍵字,我只是想簡要地解釋一下。
我最後一次使用科特林是2015年12月,當我把它用來solve a couple of Project Euler problems.使用JavaScript庫在科特林
這一次我想嘗試它使用JavaScript的互操作性。現在我的問題是,我們如何在Kotlin中導入/使用現有的Javascript庫? 我見過一些人使用native
關鍵字,我只是想簡要地解釋一下。
有沒有native
關鍵字了,有@native
註釋。目前,它是工作解決方案,您可以將它與Kotlin編譯器的1.0.x分支結合使用。不過,我們將會棄用這個註解來支持extern
註解,所以請準備好最終爲1.1.x分支重寫您的代碼。
當你把@native
註解一個類或一個頂級功能,發生兩件事情:
我覺得它更容易通過提供一個JavaScript庫的例子來解釋:
function A(x) {
this.x = x;
this.y = 0;
}
A.prototype.foo = function(z) {
return this.x + this.y + z;
}
function min(a, b) {
return a < b ? a : b;
}
和相應的科特林聲明
@native class A(val x: Int) {
var y: Int = noImpl
fun foo(z: Int): Int = noImpl
}
@native fun min(a: Int, b: Int): Int = noImpl
注意noImpl
是的需要的,因爲一個特殊的佔位符非抽象函數所需的主體和非抽象屬性需要初始化器。順便說一下,當我們用extern
代替@native
時,我們將擺脫這個noImpl
。
與JS庫互操作的另一個方面是通過模塊系統包含庫。抱歉,我們目前沒有任何解決方案(但即將發佈)。見proposal。您可以使用以下解決方法的node.js/CommonJS的:
@native interface ExternalModule {
fun foo(x: Int)
}
@native fun require(name: String): dynamic = noImpl
fun main(args: Array<String>) {
val module: ExternalModule = require("externalModule")
module.foo(123)
}
,其中外部模塊聲明如下
function foo(x) {
return x + 1;
}
module.exports = { foo : foo };
哇,非常專業的答案!謝謝 :) –
科特林1.1引入了external
改性劑可用於書面聲明函數和類直接在JS中,請參見http://kotlinlang.org/docs/reference/js-interop.html
我添加了一個簡單的準系統項目,作爲如何執行Kotlin2Js的示例。
https://bitbucket.org/mantis78/gradle4kotlin2js/src
這裏是gradle這個文件的主要配方。
group 'org.boonhighendtech'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.2-5'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
build {
outputs.dir("web/")
}
build.doLast {
copy {
from 'src/main/webapp'
into 'web/'
include '**/*.html'
include '**/*.js'
include '**/*.jpg'
include '**/*.png'
}
configurations.compile.each { File file ->
copy {
includeEmptyDirs = false
from zipTree(file.absolutePath)
into "${projectDir}/web"
include { fileTreeElement ->
def path = fileTreeElement.path
path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
}
}
}
}
clean.doLast {
file(new File(projectDir, "/web")).deleteDir()
}
compileKotlin2Js {
kotlinOptions.outputFile = "${projectDir}/web/output.js"
kotlinOptions.moduleKind = "amd"
kotlinOptions.sourceMap = true
}
首先,您可以指定一個動態變量,然後根據代碼動態地編寫代碼。
例如
val jQuery: dynamic = passedInJQueryRef
jQuery.whateverFunc()
但是,如果您的意圖是要輸入它,那麼您需要將類型引入外部庫。一種方法是利用相對廣泛的typedefs庫https://github.com/DefinitelyTyped/DefinitelyTyped
找到ts.d那裏,然後運行ts2kt(https://github.com/Kotlin/ts2kt)來獲取您的Kotlin文件。這通常會讓你在那裏。有時候,某些轉換沒有做好。您將不得不手動修復轉換。例如。 snapsvg的snapsvg.attr()調用需要「{}」,但它被轉換爲一些奇怪的界面。
這是
fun attr(params: `ts$2`): Snap.Element
和我一起
fun attr(params: Json): Snap.Element
取代它,它就像一個魅力。
可能是很好的閱讀起點的地方:https://discuss.kotlinlang.org/c/javascript,Kotlin Slack #javascript頻道,以及這個其他的SO問題http://stackoverflow.com/questions/36250680/寫-javascript-applications-kotlin –