【问题标题】:How to call Kotlin/JS functions from regular Javascript?如何从常规 Javascript 调用 Kotlin/JS 函数?
【发布时间】:2020-02-17 19:59:09
【问题描述】:

我一直在使用 Kotlin 开发一个小型 2D 模拟软件,并且我正在使用 Kotlin 多平台项目使其在 JVM 和浏览器上运行。到目前为止,它运行良好。

但是,当我想从常规 Javascript 调用 Kotlin/JS 中定义的函数时,我遇到了问题。

为了让我的应用程序在浏览器中运行,我在运行“build”Gradle 任务后包含了位于“build/distributions”文件夹下的大 JS 文件。当我的 Kotlin/JS 应用程序包含一个 main() 函数时,当打开引用 JS 文件的 HTML 页面时会自动调用这个函数,并且运行良好。

但是,如果我删除了 main 函数,而是创建了一个应该手动调用的 start() 函数(例如,在单击按钮之后),它将不起作用:它说函数 start() 没有定义,即使它是在 Kotlin 代码中声明的。

打开生成的JS文件后,好像确实没有start()函数。看起来所有函数的名称都被缩小了。

我尝试添加 @JsName,但没有任何改变。

所以我想我做错了什么,但我真的不知道是什么以及如何让它发挥作用。

注意:我使用的是 Kotlin 1.3.70

编辑:这是我的 build.gradle.kts 的核心:

plugins {
    kotlin("js") version "1.3.70-eap-184"
}


repositories {
    mavenLocal()
    mavenCentral()

    maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
}

dependencies {

}

kotlin {
    target {
        nodejs {

        }
        browser {
            webpackTask {
                mode = org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode.PRODUCTION
                bin = "$projectDir/node_modules/$bin"
            }
        }
    }
}

【问题讨论】:

    标签: javascript gradle kotlin kotlin-js


    【解决方案1】:

    您应该使用模块名称和限定名称调用函数:

    https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#package-structure

    package my.qualified.packagename
    
    fun foo() = "Hello"
    
    alert(myModule.my.qualified.packagename.foo());
    

    https://kotlinlang.org/docs/reference/js-to-kotlin-interop.html#jsname-annotation

    在某些情况下(例如,为了支持重载),Kotlin 编译器会破坏 JavaScript 代码中生成的函数和属性的名称。要控制生成的名称,您可以使用 @JsName 注解

    更新: 您有两种方法可以更改模块名称:

    1) 如果您使用 gradle,您可以将此代码添加到您的 build.gradle

    compileKotlinJs {
        kotlinOptions.outputFile = "${rootDir}/web/app.js" // should be valid js variable name
    }
    

    或在您的build.gradle.kts

    kotlin {
        target {
            compilations.all {
                kotlinOptions.outputFile = "${rootDir}/web/app.js"
            }
        }
    }
    

    在这种情况下,您应该使用 web 文件夹中的生成文件 (app.js) (您可以使用其他文件夹和文件名)。

    2)你应该创建文件夹webpack.config.d并创建任何名称的js文件,以及为webpack配置库模式的内容

    config.output = config.output || {} // just in case where config.output is undefined
    config.output.library = "libraryName" // should be valid js variable name
    

    【讨论】:

    • 我不确定我应该调用的模块名称。我在 Intellij IDEA 中的模块称为“sim-view-js”。我必须重命名我的 Intellij 模块还是有办法调用“sim-view-js.mypackage.foo()”?
    • 你应该叫它sim-view-js.mypackage.foo(),其中mypackage是你的包的名字。
    • sim-view-js 不是有效的 Javascript 名称。我不能这样称呼它。
    • 感谢您的回答,但我仍然面临一些问题。方法 (1) 正在生成一个具有正确名称的模块,但我无法轻松地将其包含在 HTML 视图中,因为“找不到模块 kotlin.js”。使用方法(2)我清楚地公开了我的模块的名称,但没有公开函数的名称(在 webpack 包中,我有“未找到静态导出”行)。
    • 经过新的测试,方法 (2) 有效。只是我需要一个 main() 函数,即使是空的。没有这个功能,其他的都不会暴露。主要功能必须参考我要暴露的功能。由于我不希望调用这些函数,因此我将它们包装在 if(false) {} 语句中。
    猜你喜欢
    • 2017-11-06
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多