vue.js - 如何将数据添加到 Kotlin 对象并在 Vuejs 页面上获取它

标签 vue.js kotlin

我对 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 方面?

并获取 HeaderBar.vue 上的 items。我不确定,但我通过以下方式做到这一点:

    <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 写你的例子。

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

让我们创建具有以下结构的项目: project structure

应用程序.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 创建的,我把这个脚本放到了底部,因为 Vue 需要开始他的操作,然后所有必要的 html 标签都已经存在。

我的带有 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"
}

设置.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 需要一个完整版本来编译模板,所以需要在中添加别名网页包。而且我不知道如何在 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/

相关文章:

vue.js - toast 未识别

vue.js - 在 Vue JS 组件中动态添加和删除 div

javascript - Vue 子组件属性不起作用

firebase - 在 vuex 操作中访问 this.$fireStore (Nuxt.js)

Kotlin 接口(interface)类型参数

kotlin - 将列表映射到以下元素的元组

java - 如何在 Kotlin 中删除布局参数标志?

vue.js - Vue + Vuex : input value not set by store if no store change

android - 确定 Android 可用的生物识别硬件类型

kotlin - 使用适用于桌面的 Kotlin 多平台进行 http 请求