在Kotlin中使用Javascript库

我最后一次使用Kotlin的时候是2015年12月,当时我用它来解决一些欧拉项目问题。

这一次我想尝试与Javascript的互操作性。 现在我的问题是,我们如何在Kotlin中导入/使用现有的Javascript库? 我见过一些使用native关键字的人,我只是想简单地解释一下。

没有native关键字了,还有@native注释。 目前,它是工作的解决方案,你可以使用它与Kotlin编译器的1.0.x分支。 但是,我们要做的是赞成extern注释,而不赞成使用这个注释,所以准备好最终为1.1.x分支重写你的代码。

当您将@native注释放在类或顶级函数上时,会发生两件事情:

  1. 它的正文没有被编译成JavaScript。
  2. 编译器直接引用这个类或函数,没有包名称和变形。

我认为通过提供一个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; } 

和相应的Kotlin声明

 @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库互操作的另一个方面是通过模块系统包含库。 对不起,我们目前没有任何解决方案(但即将发布)。 见建议 。 您可以对node.js / CommonJS使用以下解决方法:

 @native interface ExternalModule { fun foo(x: Int) } @native fun require(name: String): dynamic = noImpl fun main(args: Array) { val module: ExternalModule = require("externalModule") module.foo(123) } 

外部模块是这样声明的

 function foo(x) { return x + 1; } module.exports = { foo : foo }; 

Kotlin 1.1引入了可用于声明直接用JS编写的函数和类的external修饰符,请参阅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 } 

首先,您可以分配一个动态variables,然后像编写JavaScript一样动态地编写动态variables。

例如

 val jQuery: dynamic = passedInJQueryRef jQuery.whateverFunc() 

但是,如果你的意图是要输入,那么你需要将types引入到外部库。 一种方法是通过https://github.com/DefinitelyTyped/DefinitelyTyped使用相对广泛的typedefs库

在那里findts.d,然后运行ts2kt( https://github.com/Kotlin/ts2kt )来获取你的Kotlin文件。 那通常让你在那里。 偶尔,某些转换没有做好。 您将不得不手动修复转换。 例如snapsvg的snapsvg.attr()调用需要“{}”,但它被转换为一些奇怪的界面。

它是

 fun attr(params: `ts$2`): Snap.Element 

我把它换了

  fun attr(params: Json): Snap.Element 

它就像一个魅力。