我上次使用Kotlin的时间是2015年12月,当时我用它来solve a couple of Project Euler problems.
这次我想尝试与Javascript的互操作性。现在我的问题是,我们如何在Kotlin中导入/使用现有的Javascript库?
我看到有些人使用native
关键字,我只想简要解释一下。
答案 0 :(得分:6)
不再有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;
}
和相应的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
是一个特殊的占位符,因为非抽象函数需要主体和非抽象属性需要初始值设定项。顺便说一句,当我们用@native
替换extern
时,我们将摆脱这个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 :(得分:2)
我添加了一个简单的准系统项目,作为如何做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
}
首先,您可以指定一个动态变量,然后基本上像编码JavaScript一样对其进行动态编码。
e.g。
val jQuery: dynamic = passedInJQueryRef
jQuery.whateverFunc()
但是如果您打算输入它,那么您需要将类型引入外部库。一种方法是通过https://github.com/DefinitelyTyped/DefinitelyTyped
使用相对广泛的typedef库在那里找到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
它就像一个魅力。
答案 2 :(得分:0)
Kotlin 1.1引入了external
修饰符,可以用来声明直接用JS编写的函数和类,参见http://kotlinlang.org/docs/reference/js-interop.html