2016-09-20 5 views
8

Das letzte Mal habe ich Kotlin war 2015 Dezember, als ich es zu solve a couple of Project Euler problems. verwendetVerwenden Javascript-Bibliotheken in Kotlin

Dieses Mal möchte ich seine Interoperabilität mit Javascript, um zu versuchen. Nun meine Frage ist, wie importieren/verwenden wir vorhandene Javascript-Bibliotheken in Kotlin? Ich habe einige Leute gesehen, die das native Schlüsselwort verwenden, und ich will nur eine kurze Erklärung davon.

+1

Orte, die gute Startpunkte für das Lesen sein könnten: https://discuss.kotlinlang.org/c/javascript, Kotlin Slack # Javascript-Kanal und diese andere SO Frage http://StackOverflow.com/Questions/36250680/ schreiben-javascript-applications-with-kotlin –

Antwort

6

Es gibt kein native Schlüsselwort mehr, es gibt @native Annotation. Momentan ist es eine funktionierende Lösung und Sie können sie mit dem 1.0.x-Zweig des Kotlin-Compilers verwenden. Wir werden diese Annotation jedoch zugunsten von extern Annotationen ablehnen. Bereiten Sie sich daher darauf vor, Ihren Code eventuell für den Zweig 1.1.x neu zu schreiben.

Wenn Sie @native Anmerkung auf eine Klasse setzen oder auf einem Top-Level-Funktion, passieren zwei Dinge:

  1. Sein Körper ist nicht zu JavaScript kompiliert.
  2. Compiler verweist direkt auf diese Klasse oder Funktion, ohne Paketname und Mangling.

Ich denke, es ist einfacher, indem Beispiel für eine JavaScript-Bibliothek zu erklären:

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; 
} 

und eine entsprechende Kotlin Erklärung

@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 

Beachten Sie, dass noImpl eine spezielle Platzhalter, die wegen der erforderlich ist Nicht abstrakte Funktionen benötigte Körper und nicht abstrakte Eigenschaften erfordern Initialisierer. BTW, wenn wir @native durch extern ersetzen, werden wir dieses noImpl loswerden.

Ein weiterer Aspekt der Zusammenarbeit mit JS-Bibliotheken ist die Einbindung von Bibliotheken über das Modulsystem. Entschuldigung, wir haben momentan keine Lösung (werden sie aber bald veröffentlichen). Siehe proposal. Sie können die folgende Problemumgehung für node.js/Commonjs verwenden:

@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) 
} 

wo externes Modul wie diese

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

Wow, eine sehr kompetente Antwort! Vielen Dank :) –

-1

Ich fügte ein einfaches Barebone-Projekt als ein Beispiel, wie man Kotlin2Js.

https://bitbucket.org/mantis78/gradle4kotlin2js/src

Hier ist die gradle-Datei, die das Haupt-Rezept.

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 
} 

Erstens, Sie können eine dynamische Variable zuweisen dann im Wesentlichen Code wie Sie JavaScript dynamisch codieren.

z.B.

val jQuery: dynamic = passedInJQueryRef 
jQuery.whateverFunc() 

Aber wenn Ihre Absicht, es eingegeben haben, dann müssen Sie Typen an die externe Bibliothek einzuführen. Eine Möglichkeit besteht darin, die relativ umfangreichen Bibliotheken von typedefs zu verwenden, indem Sie

Suchen Sie dort die Ts.D, dann führen Sie ts2kt (https://github.com/Kotlin/ts2kt), um Ihre Kotlin-Dateien zu erhalten. Das bringt dich normalerweise dorthin. Gelegentlich sind bestimmte Conversions nicht gut gelungen. Sie müssen die Konvertierung beheben. Z.B. snapsvgs Aufruf snapsvg.attr() nimmt "{}" auf, aber es wurde in eine seltsame Schnittstelle konvertiert.

Es war

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

Und ich ersetzte es durch

fun attr(params: Json): Snap.Element 

und es wirkt wie ein Zauber.

Verwandte Themen