如何在 React-Kotlin 中导入节点module?

IT技术 javascript reactjs kotlin create-react-kotlin-app
2021-05-13 10:07:58

我使用 create-react-kotlin-app 命令创建了一个应用程序,它可以在 Chrome 中正常加载。我通过 NPM 添加了 React Material UI 包并且成功了。现在如何在我的组件中使用 Material UI module?

通常在 JavaScript 中,它import Button from '@material-ui/core/Button'在组件文件的顶部是一个简单的内容,但 Kotlin 不喜欢这样。

我如何将该行翻译成 Kotlin?我没有使用 Gradle。

2个回答

我已经为这个问题苦苦挣扎了好几天了。我想出了以下解决方案。首先我们将看到多种声明外部module的方法,然后我将展示如何使用它们。

考虑以下 javascript 代码

import Button from '@material-ui/core/Button' // this means button is exported as default

这将通过以下方式在 kotlin 中导入

按钮.kt

@file:JsModule("@material-ui/core/Button")
@file:JsNonModule

package com.mypckage.mykillerapp

import react.Component
import react.RProps
import react.RState
import react.ReactElement

@JsName("default") // because it was exported as default
external val Button : RClass<RProps>

// way 2
@JsName("default")
external class Button : Component<RProps,RState> {
    override fun render(): ReactElement?
}

但同样,如果针对 kotlin 的语句必须与下面的 javascript import 语句匹配,

import { Button } from "material-ui" // not exported as default

我们使用以下方法:Button.kt

@file:JsModule("material-ui")
@file:JsNonModule

package com.mypckage.mykillerapp

import react.Component
import react.RProps
import react.RState
import react.ReactElement

// way 1
@JsName("Button") // because it was exported as default
external val Button : RClass<RProps>

// way 2
@JsName("Button")
external class Button : Component<RProps,RState> {
    override fun render(): ReactElement?
}

一旦您声明了如何使用您的组件,您就可以按如下方式使用它们:

//way 1:

fun RBuilder.render() {
    div {
        Button {
            attrs.asDynamic().className="submit-button"
            +"Submit"
        }
    }
}

//way 2:
fun RBuilder.render() {
    div {
        child(Button::class) {
            attrs.asDynamic().className="submit-button"
            +"Submit"
        }
    }
}

伟大的。您已导入组件。但在那之前你不依赖于 kotlin 类型安全甚至代码完成,要实现这一点,你必须去额外的长度

如下图

external interface ButtonProps: RProps {
    var className : String
    var onClick: (Event?)->Unit
    var color: String
    // . . .
    var href: String
}

然后继续将您的按钮声明为

@JsModule("@material-ui/core/Button")
@JsNonModule
@JsName("default") // because it was exported as default
external val Button : RClass<ButtonProps>

您现在可以将它与类型安全和代码完成一起使用,如下所示

fun RBuilder.render() {
    div {
        Button {
            attrs {
                className = "submit-button"
                onClick = {
                    window.alert("Vois La")   
                }
            }
            +"Submit"
        }
    }
}

希望这可以帮助。快乐编码

编辑:对于材料的UI组件社区包装这里

提示:使用方式 1,如您所见,它不那么冗长

Kotlin 的依赖导入方式接近于标准的 JS 导入:

import React from 'react';

export function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

基于使用 Kotlin 创建一个简单的 React 组件

package hello

import react.*
import react.dom.*

fun RBuilder.hello(name: String) {
    h1 {
        +"Hello, $name"
    }
}

通常(因为 Kotlin 是基于 Java 的)它使用 Gradle 工具来处理依赖项:

// part of build.gradle
kotlinFrontend {
    // ...

    npm {
        // ...

        dependency("react")
        dependency("react-dom")
        dependency("react-router")
        dependency("react-markdown")

        devDependency("css-loader")
        devDependency("babel-core")
        // ...
    }

并像上面那样引用:

HomeView.kt :

// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/HomeView.kt

import kotlinx.html.*
import org.jetbrains.demo.thinkter.model.*
import react.*
import react.dom.*
import kotlinx.coroutines.experimental.launch

ReactMarkdown.kt

// https://github.com/Kotlin/kotlin-fullstack-sample/blob/master/frontend/src/org/jetbrains/demo/thinkter/ReactMarkdown.kt

package org.jetbrains.demo.thinkter

import react.*

private val ReactMarkdown: dynamic = runtime.wrappers.require("react-markdown")

基于:kotlin-fullstack-sample


另外create-react-kotlin-app还面临着使用@JsModule()注释导入的可能性,而依赖项管理通过package.json以下标准方式处理

// src/logo/Logo.kt (outcome of creating new app)
package logo

import react.*
import react.dom.*
import kotlinext.js.*
import kotlinx.html.style

@JsModule("src/logo/react.svg")
external val reactLogo: dynamic
@JsModule("src/logo/kotlin.svg")
external val kotlinLogo: dynamic

也可以成功用于JS库的导入。

另一种方法是使用kotlinext.js.*

// index/index.kt

import kotlinext.js.*

fun main(args: Array<String>) {
    requireAll(require.context("src", true, js("/\\.css$/")))

    // ...
}

其中还提供了require(module: String)功能。