我正在编写scala-js前端框架,其主要功能是服务器端渲染。我们的想法是,有些组件可以使用document.createElement
,element.appendChild
和其他组件操作dom。在服务器上,我是子类HTMLDocument
,Element
和其他服务器,使用可以转换为纯字符串html的服务器dom实现覆盖它们的方法。所以我将scalajs-dom_sjs
依赖项添加到服务器模块并尝试这样做。但是HTMLDocument
,Element
以及其他类很可能在其构造函数中调用js.native
,这些异常会抛出异常,并且使用JVM版本的库"。哪个不明显存在。我可以使用另一种方式并实现我自己的dom库,但这是工作量的两倍,因为我必须在服务器和客户端上实现它,而使用第一种方法我只实现它一次在服务器上。
所以我的问题是:为什么禁止在服务器上如此严格地使用scala-js库版本并且有解决方法吗?
答案 0 :(得分:3)
禁止这样做的原因是,正如您所注意到的那样,DOM API充满了js.native
个。这些类未在Scala中实现。它们是浏览器的DOM API的一部分,它在JVM上没有等价物。您不能在JVM上使用scalajs-dom
中定义的类型,并期望它们执行任何有用的操作。方法的实现将来自何处?
您确实需要为JVM端实现自己的类DOM库。如果你不想重新实现"在客户端,您可以为您的类重用org.scalajs.dom
命名空间,并为它们提供与scalajs-dom
中完全相同的结构和类型(除非他们不会扩展js.Any
,显然)。
请注意,这在语义上是可疑的。扩展js.Any
的类型与普通的Scala类型没有相同的语义。你可能能够提出一些足够的兼容性"正常使用的API,但它仍然可疑。
通常,为了在服务器和客户端上启用所谓的同构DOM操作,可以编写与DOM无关的交叉编译库。在客户端,它将提供一个"渲染"函数到实际的DOM节点;在服务器端,它将呈现为以HTML格式发送到客户端的字符串。
这正是Scalatags所做的。