我最后一次使用科特林是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 –