如何将带有子项的 react-bootstrap 组件导入 kotlin-js react app
Posted
技术标签:
【中文标题】如何将带有子项的 react-bootstrap 组件导入 kotlin-js react app【英文标题】:How to import react-bootstrap component with children into kotlin-js react app 【发布时间】:2020-11-05 06:16:29 【问题描述】:我想在使用 kotlin-js 创建的反应网站中使用引导卡组件。该应用程序使用 kotlin-react 包装器和 react-bootstrap 库。
react-bootstrap 文档说使用
<Card>
<Card.Body>This is some text within a card body.</Card.Body>
</Card>
到目前为止,我设法将 Card javascript 模块导入 kotlin-js。
@file:JsModule("react-bootstrap/Card")
import react.RClass
import react.RProps
@JsName("default")
external val Card: RClass<RProps>
有了这个,我可以在 RComponent 中使用卡片。
class Content : RComponent<RProps, RState>()
override fun RBuilder.render()
Card
+"Hello World"
渲染到什么:
<div class="card">
Hello World
</div>
我还需要 CardBody 组件。
类似这样的:
class Content : RComponent<RProps, RState>()
override fun RBuilder.render()
Card
CardBody
+ "Hello World"
但是 CardBody 不是一个单独的 react-bootstrap 组件,它可以像 Card 组件一样被导入。它是 Card 组件内部的一个值。
打字稿定义文件Card.d.ts如下所示:
import CardImg from './CardImg';
import BsPrefixPropsWithChildren, BsPrefixRefForwardingComponent from './helpers';
import Color, Variant from './types';
declare const CardBody: BsPrefixRefForwardingComponent<any, >;
declare const CardTitle: BsPrefixRefForwardingComponent<any, >;
declare const CardSubtitle: BsPrefixRefForwardingComponent<any, >;
declare const CardLink: BsPrefixRefForwardingComponent<any, >;
declare const CardText: BsPrefixRefForwardingComponent<any, >;
declare const CardHeader: BsPrefixRefForwardingComponent<any, >;
declare const CardFooter: BsPrefixRefForwardingComponent<any, >;
declare const CardImgOverlay: BsPrefixRefForwardingComponent<any, >;
export interface CardProps extends BsPrefixPropsWithChildren
bg?: Variant;
text?: Color;
border?: Variant;
body?: boolean;
declare type Card = BsPrefixRefForwardingComponent<'div', CardProps> &
Img: typeof CardImg;
Title: typeof CardTitle;
Subtitle: typeof CardSubtitle;
Body: typeof CardBody;
Link: typeof CardLink;
Text: typeof CardText;
Header: typeof CardHeader;
Footer: typeof CardFooter;
ImgOverlay: typeof CardImgOverlay;
;
declare const Card: Card;
export default Card;
如果我使用 dukat 将 TypeScript 定义文件转换为 Kotlin 声明。它会输出一个 Card.module_react-bootstrap.kt 文件
@file:JsModule("react-bootstrap")
@file:JsNonModule
@file:Suppress("INTERFACE_WITH_SUPERCLASS", "OVERRIDING_FINAL_MEMBER", "RETURN_TYPE_MISMATCH_ON_OVERRIDE", "CONFLICTING_OVERLOADS")
import kotlin.js.*
import kotlin.js.Json
import org.khronos.webgl.*
import org.w3c.dom.*
import org.w3c.dom.events.*
import org.w3c.dom.parsing.*
import org.w3c.dom.svg.*
import org.w3c.dom.url.*
import org.w3c.fetch.*
import org.w3c.files.*
import org.w3c.notifications.*
import org.w3c.performance.*
import org.w3c.workers.*
import org.w3c.xhr.*
external var CardBody: BsPrefixRefForwardingComponent<Any, Any>
external var CardTitle: BsPrefixRefForwardingComponent<Any, Any>
external var CardSubtitle: BsPrefixRefForwardingComponent<Any, Any>
external var CardLink: BsPrefixRefForwardingComponent<Any, Any>
external var CardText: BsPrefixRefForwardingComponent<Any, Any>
external var CardHeader: BsPrefixRefForwardingComponent<Any, Any>
external var CardFooter: BsPrefixRefForwardingComponent<Any, Any>
external var CardImgOverlay: BsPrefixRefForwardingComponent<Any, Any>
external interface CardProps : BsPrefixPropsWithChildren
var bg: dynamic /* String | String | String | String | String | String | String | String | String? */
get() = definedExternally
set(value) = definedExternally
var text: String? /* 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | 'white' | 'muted' */
get() = definedExternally
set(value) = definedExternally
var border: dynamic /* String | String | String | String | String | String | String | String | String? */
get() = definedExternally
set(value) = definedExternally
var body: Boolean?
get() = definedExternally
set(value) = definedExternally
external interface `T$0`
var Img: Any
var Title: Any
var Subtitle: Any
var Body: Any
var Link: Any
var Text: Any
var Header: Any
var Footer: Any
var ImgOverlay: Any
@JsName("default")
external var Card: BsPrefixRefForwardingComponent<String /* 'div' */, CardProps> /* BsPrefixRefForwardingComponent<String /* 'div' */, CardProps> & `T$0` */
但这不能编译。
-
如何为内部包含子组件而不是单独的组件文件的组件编写 kotlin 声明文件?
如何在 RBuilder.render() 方法中使用该组件?
【问题讨论】:
【参考方案1】:阅读 Typescript 声明,似乎
文件:Card.kt
@file:JsModule("react-bootstrap/Card")
package bootstrap
import react.RClass
import react.RProps
@JsName("default")
external val Card: RClass<RProps>
文件:Card.ktx.kt(因为在 JsModule 中不能有非外部声明)
package bootstrap
import react.RClass
import react.RProps
val CardBody : RClass<RProps> = Card.asDynamic().Body
val CardLink : RClass<RProps> = Card.asDynamic().Link
用法
fun RBuilder.MyComp()
Card
CardBody +"Card body goes here"
应该可以。
【讨论】:
此解决方案有效! 不知道 Card.ktx.kt 文件。谢谢@andylamax 这太好了,谢谢。有没有办法将自定义 CSS(如字体和边距)添加到这样的外部元素?我们如何为外部组件做类似css fontFamily = "sans-serif"
的事情?
我找不到关于该 ktx.kt 扩展的任何文档?有链接吗?
没有。这不是我用来调用具有某些扩展行为的文件的一种方式。没必要叫*.ktx.kt
,可以叫*.kt
【参考方案2】:
如果你想对外部元素使用 css,你可以这样做,
首先你需要让你的元素道具实现 WithClassName 接口:
@file:JsModule("react-bootstrap")
@file:JsNonModule
import react.RProps
import react.RClass
import react.dom.WithClassName
@JsName("Card")
external val bsCard : RClass<bsCardProps>
external interface bsCardProps: WithClassName
然后在另一个 .kt 文件中使用样式函数,如下所示:
import styled.styled
val styledBsCard = styled(bsCard)
现在使用 styledBsCard 之类的样式元素:
override fun RBuilder.render()
styledBsCard
css
width = 200.px
backgroundColor = Color.blue
marginLeft = 100.px
//something other elements
【讨论】:
以上是关于如何将带有子项的 react-bootstrap 组件导入 kotlin-js react app的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 React-Bootstrap 根据项目计数创建带有拼接的轮播项目
带有图标的 React-Bootstrap FormControl
使用带有打字稿的 react-bootstrap Form.Label 时出现类型错误