加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为API包装器实例化js.Object的建议方法是什么

发布时间:2020-12-16 09:26:53 所属栏目:安全 来源:网络整理
导读:对于以下javascript API包装器: @JSName("React")object React extends js.Object { def createClass(init: ReactClassInit): ReactClassBuilder = ???} 建议实例化以下特征的建议是什么 trait ReactClassInit extends js.Object { val render: js.ThisFunc
对于以下javascript API包装器:

@JSName("React")
object React extends js.Object {
  def createClass(init: ReactClassInit): ReactClassBuilder = ???
}

建议实例化以下特征的建议是什么

trait ReactClassInit extends js.Object {
  val render: js.ThisFunction0[js.Dynamic,js.Any]
}

目前我正在做以下事情:

val * = js.Dynamic.literal
val init = *(render = new js.ThisFunction0[js.Dynamic,js.Any] {
  override def apply(thisArg: js.Dynamic): js.Any = {
    React.DOM.div(null,"Hello ",thisArg.props.name)
  }
}).asInstanceOf[ReactClassInit]
val HelloMessage = React.createClass(init)

我不喜欢这种方法是没有类型安全
确保正确实例化ReactClassInit.

(以下是将事物置于更好的上下文中的所有代码)

//Work in progress React wrapers
@JSName("React")
object React extends js.Object {
  def createClass(init: ReactClassInit): ReactClassBuilder = ???
  def renderComponent(cls: ReactClassInstance,mountNode: HTMLElement) = ???
  val DOM: ReactDOM = ???
}

trait ReactDOM extends js.Object {
  def div(huh: js.Any,something: js.String,propsOrWhat: js.Any) = ???
}

trait ReactClassInstance extends js.Object

trait ReactClassBuilder extends js.Object {
  def apply(args: js.Object): ReactClassInstance
}

trait ReactClassInit extends js.Object {
  val render: js.ThisFunction0[js.Dynamic,js.Any]
}



@JSExport
object ReactTodo {
  //Some helpers I use.
  val * = js.Dynamic.literal

  @JSExport
  def main() {
    helloJonT()
  }


  //Ideal Typed Example
  def helloJonT() {
    val init = *(render = new js.ThisFunction0[js.Dynamic,js.Any] {
      override def apply(thisArg: js.Dynamic): js.Any = {
        React.DOM.div(null,thisArg.props.name)
      }
    }).asInstanceOf[ReactClassInit]
    val HelloMessage = React.createClass(init)
    React.renderComponent(HelloMessage(*(name = "Jon").asInstanceOf[js.Object]),document.getElementById("content"))
  }

}

解决方法

目前,推荐的方法与您正在做的非常接近,除了应该将js.Dynamic.literal的使用封装在特征的伴随对象中(在您的情况下为ReactClassInit).您可以在该伴随对象中提供类型安全的应用方法,如下所示:

trait ReactClassInit extends js.Object {
  val render: js.ThisFunction0[js.Dynamic,js.Any]
}
object ReactClassInit {
  def apply(render: js.ThisFunction0[js.Dynamic,js.Any]): ReactClassInit = {
    js.Dynamic.literal(
      render = render
    ).asInstanceOf[ReactClassInit]
  }
}

你可以用它来:

val init = ReactClassInit(render = { (thisArg: js.Dynamic) =>
  React.DOM.div(null,thisArg.props.name)
})

当然,这仍然是全球不安全的.但是在代码中只有一点使用强制转换,更重要的是它接近于类型的定义.因此,如果您更新一个,则更有可能更新另一个.

我知道这不是一个完全令人满意的解决方案.但到目前为止,在我们的Scala.js设计中,我们还没有找到一个非常好的解决方案来解决这个问题.

两个旁注:

1)我强烈建议不要使用新的js.ThisFunctionN {def apply}!这种符号完全奏效是一个意外.简单地使用我在我的例子中展示的lambda.如果目标类型已经被输入为js.ThisFunctionN(就像在我的代码中那样),它就会像那样工作.如果,如代码中的情况,目标类型是js.Any(或Any),则需要将lambda归为:js.ThisFunction(不带数字),以确保编译器将其视为此-function而不是(非this-)函数,但这就是全部.为了更清楚,以下是您的代码看起来如何:

val init = *(render = { (thisArg: js.Dynamic) =>
  React.DOM.div(null,thisArg.props.name)
}: js.ThisFunction).asInstanceOf[ReactClassInit]

2)你可能希望你的函数被输入为返回Any(或_)而不是js.Any:

trait ReactClassInit extends js.Object {
  val render: js.ThisFunction0[js.Dynamic,Any]
}

通常,当你在js.(This)函数的结果类型中使用js.Any时,你的意思是任何值,而不是任何JS值. Scala的类型推断最适合在该位置使用Any.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读