2016-09-20 25 views
8

Lần cuối cùng tôi đã sử dụng Kotlin là tháng 12 năm 2015 khi tôi sử dụng nó để solve a couple of Project Euler problems.thư viện Sử dụng Javascript trong Kotlin

Lần này tôi muốn thử khả năng tương tác của nó với Javascript. Bây giờ câu hỏi của tôi là, làm cách nào để chúng tôi nhập/sử dụng các thư viện Javascript hiện có trong Kotlin? Tôi đã thấy một số người sử dụng từ khóa native và tôi chỉ muốn giải thích ngắn gọn về từ khóa đó.

+1

Địa điểm có thể là điểm bắt đầu tốt để đọc: https://discuss.kotlinlang.org/c/javascript, kênh Kotlin Slack #javascript và câu hỏi SO khác http://stackoverflow.com/questions/36250680/ viết-javascript-ứng dụng-với-kotlin –

Trả lời

6

Không còn native từ khóa nữa, có chú thích @native. Hiện tại, nó là giải pháp làm việc và bạn có thể sử dụng nó với nhánh 1.0.x của trình biên dịch Kotlin. Tuy nhiên, chúng tôi sẽ ngừng sử dụng chú thích này để ủng hộ các chú thích extern, vì vậy hãy chuẩn bị để viết lại mã của bạn cuối cùng cho chi nhánh 1.1.x.

Khi bạn đặt @native chú thích trên một lớp học hoặc trên một hàm cấp cao nhất, có hai điều xảy ra:

  1. cơ thể của nó không được biên dịch JavaScript.
  2. Trình biên dịch tham chiếu lớp hoặc chức năng này trực tiếp, không có tên gói và mangling.

Tôi nghĩ rằng nó dễ dàng hơn để giải thích bằng cách cung cấp ví dụ về một thư viện 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; 
} 

và tuyên bố Kotlin tương ứng

@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 

Lưu ý rằng noImpl là một giữ chỗ đặc biệt đó là cần thiết vì các hàm không trừu tượng bắt buộc các đối tượng và các thuộc tính không trừu tượng yêu cầu khởi tạo. BTW, khi chúng tôi thay thế @native bằng extern, chúng tôi sẽ loại bỏ điều này noImpl.

Một khía cạnh khác của tương tác với các thư viện JS là bao gồm thư viện thông qua hệ thống mô-đun. Xin lỗi, chúng tôi không có bất kỳ giải pháp nào ngay bây giờ (nhưng sẽ sớm phát hành). Xem proposal. Bạn có thể sử dụng workaround sau cho 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) 
} 

nơi mô-đun bên ngoài được khai báo như thế này

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

Wow, một câu trả lời rất chuyên gia! Cảm ơn bạn :) –

-1

Tôi đã thêm một dự án barebone đơn giản làm ví dụ về cách thực hiện Kotlin2J.

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

Dưới đây là file gradle đó là công thức chính.

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 
} 

Thứ nhất, bạn có thể gán biến động, sau đó về cơ bản mã nó giống như mã JavaScript, động.

ví dụ:

val jQuery: dynamic = passedInJQueryRef 
jQuery.whateverFunc() 

Nhưng nếu bạn có ý định nhập, thì bạn cần giới thiệu các loại cho thư viện bên ngoài. Một cách là sử dụng các thư viện tương đối phong phú của typedefs bằng cách https://github.com/DefinitelyTyped/DefinitelyTyped

Tìm ts.d ở đó, sau đó chạy ts2kt (https://github.com/Kotlin/ts2kt) để tải tệp Kotlin của bạn. Điều đó thường đưa bạn đến đó. Đôi khi, một số chuyển đổi nhất định không được thực hiện tốt. Bạn sẽ phải sửa chữa chuyển đổi. Ví dụ. Lệnh snapsvg.attr() của snapsvg có trong "{}" nhưng nó đã được chuyển đổi thành một số giao diện lạ.

Đó là

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

Và tôi đã thay thế nó với

fun attr(params: Json): Snap.Element 

và nó hoạt động như một nét duyên dáng.

Các vấn đề liên quan