如何将 Javascript 中的 JQuery 翻译成 ScalaJS (scalajs-jquery)

How to translate JQuery in Javascript to ScalaJS (scalajs-jquery)

在我的 ScalaJS 项目中我使用 Semantic-UI with scala-js-jquery

我用这个来打补丁 JQuery:

  // Monkey patching JQuery
  @js.native
  trait SemanticJQuery extends JQuery {
    def dropdown(params: js.Any*): SemanticJQuery = js.native
    def popup(params: js.Any*): SemanticJQuery = js.native
    // and more
  }

  // Monkey patching JQuery with implicit conversion
  implicit def jq2semantic(jq: JQuery): SemanticJQuery = jq.asInstanceOf[SemanticJQuery]

例如$('select.dropdown').dropdown();

转换为 jQuery(".ui.dropdown").dropdown(js.Dynamic.literal(on = "hover"))

我现在的问题是如何翻译这个:

$('.ui.form')
  .form({
    fields: {
      dog: {
        identifier: 'dog',
        rules: [
          {
            type: 'adminLevel[2]',
            prompt: 'You must be at least a level-2 admin to add a dog'
          }
        ]
      }
    }
  });

首先解决更简单的问题 #2(其他人可能会解决 #1):要记住的关键是它确实是一个 JavaScript 数据结构;将其视为 JSON 会分散注意力。所以你通常使用 strongly-typed 门面实例化它,就像 JavaScript.

的其余部分一样

您可以找到关键文档 here,但粗略地说外观类似于:

trait Rules extends js.Object {
  def `type`: String
  def prompt: js.UndefOr[String] = js.undefined
}

我在这里将 type 设为必填项,将 prompt 设为可选项,以显示您处理这些字段的方式的差异。 (而且由于 "type" 是 Scala 中的关键字,您必须解决这个问题;我认为 认为 反引号会起作用。)

然后您通过创建一个匿名子类实例来实例化它,如下所示:

new Rules {
  override val `type` = "adminLevel[2]"
  override val prompt = "You must be at least a level-2 admin to add a dog"
}

基本上,它是相当普通的 Scala,但是 extends js.Object 是编译器的魔法——它告诉编译器输出应该是 JavaScript-readable 类型,而不是内部 Scala 类型。

对于外包装,基本上是一样的——像这样的 deeply-nested 结构有点麻烦,但基本上只是为每个 strongly-typed 创建一个小外观特征的问题水平。

对于 weakly-typed 级别(例如,dog,我假设它没有在库中定义),您可能想要使用 js.Dynamic.literal,它可以让您创建任意JavaScript 数据结构,完全没有强类型。 (当然,您也可以这样做来创建 Rules,但是如果过度使用它,您将失去使用 Scala 的很多好处。)

请注意,以上内容的详细信息因您使用的 Scala.js 版本而异——有关详细信息,请参阅文档。但这就是它的大致运作方式...

根据 Justin du Coeur 的回答,它成功了!

为了完整起见,这里是整个解决方案(因为它是静态和动态部分的组合):

trait Form extends js.Object {
  def fields: js.Object
}

trait Field extends js.Object {
  def identifier: String
  def rules: js.Array[Rule]
}

trait Rule extends js.Object {
  def `type`: String
  def prompt: js.UndefOr[String] = js.undefined
}

这是它的用法 - 检查动态 cardNumbercardCVC:

val form = new Form {
  val fields: js.Object = js.Dynamic.literal (
    cardNumber = new Field {
      val identifier: String = "cardNumber"
      val rules: js.Array[Rule] = js.Array(new Rule {
        val `type`: String = "empty"
      })
    },
    cardCVC = new Field {
      val identifier: String = "cardCVC"
      val rules: js.Array[Rule] = js.Array(new Rule {
        val `type`: String = "validate['cardCVC']"
        override val prompt = "You must a valid CVC - see ..."
      })
    }
)}

jQuery(".ui.form").form(form)