Wrapping/facading 一个 ScalaJS 以尽可能封装的方式反应 js 组件(react-sticky)

Wrapping/facading a ScalaJS react js component (react-sticky) in the most encapsulating manner possible

我见过几种在 scala.js 中制作立面或包装 Javascript 组件的方法,包括为 react.js Component 这样做。他们似乎在封装或隐藏组件本身提供的功能的程度上有所不同,我想是根据他们的需要(也许他们只需要调用一种方法)。

在我的例子中,我需要使用一个名为 react-sticky 的组件,我首先尝试确定如何继续为其仅有的两个组件之一制作外观 classes,StickyContainer, code provided here.

我的问题如下:

  1. 如何处理 scala 中的 static Javascript 方法?我什至需要关心这个,还是我可以对此不可知?
  2. 我需要做的 最小 量是多少 "facade" 我只需要在另一个 [= 中包含 component 而没有任何 Props 19=] 的 render()?
  3. 与任何其他 js 原生 class 组件相比, 包装或外观 reactjs 组件在根本上有什么不同

最后,以下哪种策略最合适?

@js.native
trait StickyContainer extends js.Object { ... }
object StickyContainer extends StickyContainer {}

case class StickyContainer(offset: js.UndefOr[Double],...) {
    def apply() = { React.createElement(ReactUniversal.Image, JSMacro[StickyContainer](this), children: _*)
}

How do I deal with static Javascript methods in scala? Do I even need to care about this, or can I be agnostic about it?

当你想包装它时,你不需要担心反应组件的底层实现。但一般来说,如果你想为 class

指定静态字段
 @ScalaJSDefined
 class MyComponent extends ReactComponent {
  ...
}

val ctor = js.constructorOf[MyComponent]

ctor.childContextTypes = js.Dictionary("contextfield" -> React.PropTypes.`object`.isRequired)

如果您想了解 scala.js 中开箱即用的静态字段支持...... https://github.com/scala-js/scala-js/issues/1902

What is the minimum amount of "facade" I need to make to just include the component without any Props in another component's render()?

global.ReactSticky = require('react-sticky') // load js lib

@js.native
object ReactSticky extends js.Object {
  val StickyContainer : js.Dynamic = js.native
  val Sticky : js.Dynamic = js.native
}

//Using JSMacro
case class StickyContainer(fields ..) {
  def apply(children : ReactNode*) = {
     val props  = JSMacro[StickyContainer](this)
     React.createElement(ReactSticky.StickyContainer,props,children :_*) 
   }
}

//Using FunctionMacro
def StickyContainer(fields ..)(children : ReactNode*) : ReactElement = {
     val props  = FunctionMacro()
     React.createElement(ReactSticky.StickyContainer,props,children :_*) 
   }
}

What is fundamentally different about wrapping or facading a reactjs component as opposed to any other js native class?

如果看到object ReactSticky extends js.Object ...写门面没有区别。但在 React 世界中,你需要 ReactElement 这就是你需要额外包装器的地方 - React.createElement(classCtor,props,children) 调用 ..

invariant 提供关于如何使 SRI-based 组件正常工作的正确答案。其他基于 japgolly 的在处理 third-party JS 时并不友好。

以下是我如何获得库 react-mt-svg-lines,一个动画库,正在运行:

克拉兹

case class MtSvgLines(
                      key: js.UndefOr[String] = js.undefined,
                      ref: js.UndefOr[String] = js.undefined,
                      animate: js.Any = true,
                      duration: Double = 10.0,
                      stagger: js.UndefOr[Double] = js.undefined,
                      timing: js.UndefOr[String] = js.undefined,
                      playback: js.UndefOr[String] = js.undefined,
                      fade: js.UndefOr[String] = js.undefined
                    )
{

  def apply(children: ReactNode*): ReactComponentU_ = {
    val props = JSMacro[MtSvgLines](this)
    val f = React.asInstanceOf[js.Dynamic].createFactory(js.Dynamic.global.SvgLines.default)
    if (children.isEmpty)
      f(props).asInstanceOf[ReactComponentU_]
    else if (children.size == 1)
      f(props, children.head).asInstanceOf[ReactComponentU_]
    else
      f(props, children.toJsArray).asInstanceOf[ReactComponentU_]
  }

}

值得注意的是,确保 createFactory 中的参数是您 exportglobal.Whatever。考虑 children 的数字差异。对每个可选项使用 js.UndefOr

客户

def render(S: State, C: PropsChildren) = {
  <.header(^.key := UUID.randomUUID().toString, Styles.Header_TextIsCentered, Styles.Header_BackgroundIsGrayBlue_WithWhiteText)(
    <.div(^.className := "container")(
      <.h1()("justin shin, tampa fl"),
      MtSvgLines(animate = true, duration = 500) {
        import japgolly.scalajs.react.vdom.svg.all._

        svg(SvgStyles.svg,
          defs(
            maskTag(id := "mask", x := "0", y := "0", width := "100%", height := "100%",
              rect(id := "alpha", x := "0", y := "0", width := "100%", height := "100%"),
              text(id := "title", x := "50%",y := "0", dy := "1.58em")("Justin", transform := "translate(50, 0)"),
              text(id := "title", x := "50%",y := "0", dy := "1.58em")("Tampa")
            )
          ),
          rect(id := "base", x := "0", y := "0", width := "100%", height := "100%"),
          path(stroke := "green", strokeWidth := "10", fill := "none", d := "M20.8,51c0,0,20.8,18.2,21.5,18.2c0.6,0,33.3-38.5,33.3-38.5"),

        )
      }
    )
  )
}