如何在 scala.js 中提供和使用 require.js 模块(并扩展 类)

How to provide and consume require.js modules in scala.js (and extending classes)

我正在为 Atom.io https://github.com/ensime/ensime-atom 做这个 Ensime 包,我一直在考虑使用 scala.js 而不是编写 Coffeescript 的可能性。

Atom 是一个基于 Web 的编辑器,它使用 js 编写脚本并且基于 node.js。 plugin/package 通过指出具有一些特定的 javascript 对象来定义它的主要入口点。

我想我应该从简单开始并尝试使用 scala.js 替换我拥有的最简单的 coffeescript 文件:

{View} = require 'atom-space-pen-views'
# View for the little status messages down there where messages from Ensime server can be shown
module.exports =
  class StatusbarView extends View
    @content: ->
      @div class: 'ensime-status inline-block'

    initialize: ->

    serialize: ->

    init: ->
      @attach()

    attach: =>
      statusbar = document.querySelector('status-bar')
      statusbar?.addLeftTile {item: this}

    setText: (text) =>
      @text("Ensime: #{text}").show()

    destroy: ->
      @detach()

如您所见,这导出了一个 require.js 模块,并且是一个 class 扩展了一个 class 并通过 require 获取。

太棒了。

我在想我会像我在 SO :

上看到的那样使用 Dynamic 作为需求 dep
import js.Dynamic.{global => g}
import js.DynamicImplicits._

private[views] object SpacePen {
  private val spacePenViews = require("atom-space-pen-views")
  val view = spacePenViews.view
}

但是如果我想输入 super-class,我可以做一个 facade-trait 然后做 asInstanceOf 吗?

其次,我想知道如何将 class 导出为节点模块。我发现了这个:

https://github.com/rockymadden/scala-node/blob/master/main/src/main/coffeescript/example.coffee

这是正确的方法吗?我需要做沙盒吗?我不能直接从全局导入 module 并写 module.exports = _some_scala_object_ 吗?

我也想知道如何扩展现有的 js classes。和这里问的问题一样,但是我不太明白答案:

https://groups.google.com/forum/#!topic/scala-js/l0gSOSiqubs

My code so far:
private[views] object SpacePen {
  private val spacePenViews = js.Dynamic.global.require("atom-space-pen-views")
  type View = spacePenViews.view
}

class StatusBarView extends SpacePen.View  {
  override def content =
    super.div()

}

出现编译错误,无法扩展密封特征 Dynamic。当然可以。

非常感谢任何指点!

我本身并不是 Node 的专家,但要回答你的第一个问题,是的——如果你有一个指向 JS 对象的指针,并且你知道它的类型的详细信息,你几乎总是可以定义外观特征和 asInstanceOf 以使用它。应该可以。

至于最后一点,您基本上无法在 Scala.js 中扩展 JS classes -- 它根本不起作用。我们大多数人解决这个问题的方法是通过定义隐式 classes 或使用隐式 def 来获得 外观 扩展而不实际这样做。

例如,给定 JS class Foo,我可以写 implicit class RichFoo(foo:Foo) { def method1() = { ... } } 这实际上是 around Foo 的包装器,但是调用代码可以简单地调用 foo.method1() 而不必担心那个细节。

您可以在 jquery-facade, particularly in the relationship between JQuery (the pure facade), JQueryTyped (some tweaked methods over JQuery to make them work better in Scala), and JQueryExtensions(围绕 JQuery 构建的一些高级函数)中看到这种方法的实际应用。这些是使用 package.scala 中的隐式定义组合在一起的。就调用代码而言,所有这些看起来都像是 JQuery.

上的方法