【问题标题】:Make use of web component library in Kotlin Compose for Web在 Kotlin Compose for Web 中使用 Web 组件库
【发布时间】:2022-01-11 02:58:40
【问题描述】:

我想稍微修改一下 Kotlin Compose for Web。 在我过去的一些 Web 项目中,我使用了 Clarity Design System (CDS) 的一些 Web 组件。

在 JavaScript 或 TypeScript 项目中, 你首先需要安装 npm 包@cds/core@cds/city。 其次,您必须包含一些全局样式表,例如通过 HTML 或 sass 导入。 对于每个要使用的组件,都需要导入对应的register.js。 最后,您可以像任何其他标记一样在 HTML 中包含该组件:

<cds-button>Click me!</cds-button>

我尝试使用 Kotlin Compose for Web 复制这些步骤,但无法使其正常工作。 任何帮助表示赞赏!

【问题讨论】:

    标签: kotlin web-component kotlin-js jetbrains-compose compose-for-web


    【解决方案1】:

    好的,我现在已经开始工作了,其中包括几个步骤。

    1. 安装 npm 依赖项
    kotlin {
        ...
        
        sourceSets {
            val jsMain by getting {
                dependencies {
                    // dependencies for Compose for Web
                    implementation(compose.web.core)
                    implementation(compose.runtime)
    
                    // dependencies for Clarity Design System
                    implementation(npm("@cds/core", "5.6.0"))
                    implementation(npm("@cds/city", "1.1.0"))
    
                    // dependency for webpack - see step 3
                    implementation(npm("file-loader", "6.2.0"))
                }
            }
            ...
        }
    }
    
    
    1. 启用 CSS 支持
      为了包含全局样式表,这似乎是必需的。
    kotlin {
        js(IR) {
            browser {
                ... 
                commonWebpackConfig {
                    cssSupport.enabled = true
                }
            }
            ...
        }
        ...
    }
    
    
    1. 添加对 Clarity 样式表中包含的 .woff2 文件的支持
      CDS 的样式表包含.woff2 类型的字体文件,必须配置其在 webpack 中的支持。 这可以通过创建文件webpack.config.d/support-fonts.js 来实现 在项目根目录中包含以下内容:
    config.module.rules.push({
        test: /\.(woff(2)?|ttf|eot|svg|gif|png|jpe?g)(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
            loader: 'file-loader',
            options: {
                name: '[name].[ext]',
                outputPath: 'fonts/'
            }
        }]
    });
    
    1. 包括全局样式表
    external fun require(module: String): dynamic
    
    fun main() {
        require("modern-normalize/modern-normalize.css")
        require("@cds/core/global.min.css")
        require("@cds/core/styles/module.shims.min.css")
        require("@cds/city/css/bundles/default.min.css")
        
        ...
    }
    
    1. 导入 register.js 以获得所需的 Web 组件
    external fun require(module: String): dynamic
    
    fun main() {
        ...
        
        require("@cds/core/button/register.js")
    
        ...
    }
    
    1. 为 Web 组件创建 @Composable
      遗憾的是,该解决方案使用了标记为 @OptIn(ComposeWebInternalApi::class) 的 API, 代表“此 API 是内部的,将来可能会更改”。 任何关于如何在不依赖内部 API 的情况下实现这一点的提示都表示赞赏。
    @Composable
    fun CdsButton(
        status: CdsButtonStatus = CdsButtonStatus.Primary,
        attrs: AttrBuilderContext<HTMLElement>? = null,
        content: ContentBuilder<HTMLElement>? = null
    ) = TagElement(
        elementBuilder = CdsElementBuilder("cds-button"),
        applyAttrs = {
            if (attrs != null) apply(attrs)
    
            attr("status", status.attributeValue)
        },
        content = content
    )
    
    /**
     * This is a copy of the private class org.jetbrains.compose.web.dom.ElementBuilderImplementation
     */
    internal class CdsElementBuilder<TElement : Element>(private val tagName: String) : ElementBuilder<TElement> {
        private val element: Element by lazy {
            document.createElement(tagName)
        }
    
        override fun create(): TElement = element.cloneNode() as TElement
    }
    
    sealed interface CdsButtonStatus {
        object Primary : CdsButtonStatus
        ...
    }
    
    internal val CdsButtonStatus.attributeValue
        get() = when (this) {
            CdsButtonStatus.Primary -> "primary"
            ...
        }
    
    1. 让我们成为您的@Composable
    fun main() {
        ...
        
        renderComposable(rootElementId = "root") {
            CdsButton(
                status = CdsButtonStatus.Success
            ) {
                Text("It works! :-)")
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-14
      • 2023-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-05
      • 2019-10-31
      • 1970-01-01
      相关资源
      最近更新 更多