我绝对不是Kotlin的新手。我试图通过 Kotlin 在后端创建一个简单的对象,并将其放在前端 Vuejs 上。我该怎么做(这是HeaderBar.kt原始代码,我的所有尝试都被编译器拒绝了):

    object HeaderBar {

        val computed = object {
            fun items(): Array<Item> {
                items.add(Item(
                        "NY",
                        "Bill"
                ))
                return items
            }
        }

        data class Item(
                val city: String,
                val name: String
        )

    }

在 Kotlin 一边?

并在items上获取HeaderBar.vue。我不确定,但是我这样做是:
    <template>
        <div class="main-header">
            <div v-for="item in items" class="items">
                <span class="city">{{item.city}}</span>
                <span class="name">{{item.name}}</span>
            </div>
        </div>
    <template>

    <script>
        export default path.to.HeaderBar
    </script>

最佳答案

首先,这不是一个简单的问题。 Kotlin / Js不如Kotlin / Jvm那样成熟,因此有许多任务不那么简单。

首先,您需要以某种方式编译为javascript,然后将Vue附加到kotlin / javascript代码。
Webpack可以使其变得更容易,因此我写了一个简单的示例来向您展示如何在Kotlin中编写示例。

!警告!:以下所有代码仅是草稿(并且仅出于演示目的而编写),因此请特别注意在项目中使用它!

让我们创建具有以下结构的项目:
vue.js - 如何将数据添加到Kotlin对象并在Vuejs页面上获取它-LMLPHP

Application.kt:

package vue_test

fun VueJs(init: VueContext.() -> Unit) = Vue(VueContext().apply(init))

class VueContext {
    var el: String = ""
    var data: dynamic = js("{}")
}

fun main(args: Array<String>) {
    val app: dynamic = VueJs {
        el = "#app"
        data = mapOf("items" to listOf(
                Item("NY", "Bill"),
                Item("Test", "Test2")
        )).toJs()
    }
}

data class Item(
        val city: String,
        val name: String
)

fun Map<String, Any>.toJs(): dynamic {
    val result: dynamic = object {}

    for ((key, value) in this) {
        when (value) {
            is String -> result[key] = value
            is List<*> -> result[key] = (value as List<Any>).toJs()
            else -> throw RuntimeException("value has invalid type")
        }
    }

    return result
}

fun List<Any>.toJs(): dynamic {
    val result: dynamic = js("[]")

    for (value in this) {
        when (value) {
            is String -> result.push(value)
            is Item -> {
                result.push(value.toJs())
            }
            else -> throw RuntimeException("value has invalid type")
        }
    }

    return result
}

fun Item.toJs(): dynamic {
    val result: dynamic = object {}

    result["city"] = this.city
    result["name"] = this.name

    return result
}

我写了一些函数toJs,它将Kotlin对象转换为Js对象。从理论上讲,您可以使用JSON序列化来简化此过程,或者使用其他更简单的解决方案(如果存在)。

Vue.kt
@file:JsModule("vue")
package vue_test

@JsName("default")
external open class Vue(init: dynamic)

在此文件中,我们只有Vue声明。

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Test project</title>

</head>
<body class="testApp">
<h1>Kotlin-Js test</h1>

<div id="app">
    <div class="main-header">
        <div v-for="item in items" class="items">
            <span class="city">{{item.city}}</span>
            <span class="name">{{item.name}}</span>
        </div>
    </div>
</div>

<script type="text/javascript" language="JavaScript" src="frontend.bundle.js"></script>

</body>
</html>

Buldle是由webpack创建的,我将此脚本放到最下面,因为只有在所有必要的html标签已经存在时才需要Vue来开始对其进行操作。

我的带有kotlin-frontend插件和kotlin-js插件的build.gradle文件:
buildscript {
    ext.kotlin_version = '1.2.10'

    repositories {
        mavenCentral()
        jcenter()
        maven {
            url "https://dl.bintray.com/kotlin/kotlin-eap"
        }
        maven {
            url "https://repo.gradle.org/gradle/libs-releases-local"
        }
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-frontend-plugin:0.0.21"
    }
}

group 'test'
version '1.0-SNAPSHOT'

apply plugin: 'kotlin-platform-js'
apply plugin: 'org.jetbrains.kotlin.frontend'

repositories {
    mavenCentral()
}

kotlinFrontend {
    sourceMaps = true

    npm {
        dependency("vue")
    }

    webpackBundle {
        port = 8080
        bundleName = "frontend"
        contentPath = file('src/main/web')
        webpackConfigFile = project.projectDir.path + '/webpack.config.js'
    }
}

compileKotlin2Js {
    kotlinOptions.metaInfo = true
    kotlinOptions.outputFile = "$project.buildDir.path/js/${project.name}.js"
    kotlinOptions.sourceMap = true
    kotlinOptions.moduleKind = 'commonjs'
    kotlinOptions.main = "call"
}

kotlin {
    experimental {
        coroutines 'enable'
    }
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}

settings.gradle
rootProject.name = 'test-kotlin-vue'

最后一个文件,自定义Webpack配置:
var config = require('./build/WebPackHelper.js')
var path = require('path')

module.exports = {
    entry: config.moduleName,
    output: {
        path: path.resolve('./bundle'),
        publicPath: '/build/',
        filename: 'frontend.bundle.js'
    },
    module: {
        rules: []
    },
    resolve: {
        modules: [path.resolve('js'), path.resolve('..', 'src'), path.resolve('.'), path.resolve('node_modules')],
        extensions: ['.js', '.css'],
        alias: {
            'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
        }
    },
    devtool: '#source-map'
};

console.log(module.exports.resolve.modules);

使用kotlin-frontend插件,您不能使用单独的webpack配置,但是在此示例中,Vue需要完整版本才能编译模板,因此需要在webpack中添加别名。而且我不知道如何在build.gradle中做到这一点。

希望这能够帮到你!

要使用dev bundle启动项目,请运行以下命令:gradle build webpack-run,然后在浏览器中打开http://localhost:8080

停止测试运​​行命令:gradle webpack-stop

关于vue.js - 如何将数据添加到Kotlin对象并在Vuejs页面上获取它,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47884245/

10-16 00:07