首先 - 正如@Cubic 已经说过的 - 我认为你对 GHCJS 是什么感到困惑。
GHCJS 是一个编译器,可让您将 Haskell 代码编译为 Javascript - 呈现一个简单的 html/css 页面并不是它的设计任务。正如我们在德语中所说的那样,它是“Mit Kanonen auf Spatzen schießen”——或者更短的矫枉过正。
所以我会用它来为给定的 haskell 后端编写前端非常好,您可以共享所有现有类型并获得在 haskell 生态系统中的所有可维护性和安全性。
但是,即使您没有haskell 后端并且您为新颖性和好主意而奋斗- GHCJS 可能会让您感兴趣,我本人对函数式反应式编程还是很陌生,并且在学习反射/反射之前尝试过purescript(带有pux)- dom(我选择的前端 dsl)对我的大脑来说是一个挑战,也是一种乐趣——我知道这一段很自以为是,但是 reflex 中呈现的抽象似乎是正确的,并且似乎清楚地表明了其他功能性反应框架的一些缺点…</p>
那么如何使用上述库呈现上述内容:
{-# LANGUAGE OverloadedStrings #-}
import Reflex
import Reflex.Dom
main :: IO ()
main = mainWidgetWithCss "h1 {font-family: Helvetica;} p {font-family: Helvetica; color: blue;}" $ do
el "h1" $ text "Hello World!"
el "p" $ text "This is my test document"
这 - 正如我所说的 - 矫枉过正 - 当一些普通的 html/css 就足够了时,你会得到一个完整的运行时,一大块 js。但是为了在可重用组件中生成复杂的 UI,GHCJS 可能是正确的选择。
以下是我尚未编写的更复杂的组件之一 - 它模拟了一个按钮列表,我可以在单击最右边的按钮时展开这些按钮,或者缩小到其他按钮之一的大小(我将其用于类似“评价这 X 颗星”,但星星可以是任意多)。
listWidget :: MonadWidget t m => Int -> m (Event t Int)
listWidget n = leftmost <$> traverse button' [(-1)..(n+1)]
listWidget2 :: MonadWidget t m => m ()
listWidget2 = mdo
clicked <- switchPromptlyDyn <$> widgetHold (listWidget (-1))
(listWidget <$> clicked)
return ()
button' :: (MonadWidget t m, Show a) => a -> m (Event t a)
button' val = (fmap $ const val) <$> button (text . pack $ show val)
更新:
纯 Javascript 的问题是可扩展性,如果您有大量的 Javascript 维护和更改代码,由于缺少类型系统和动态特性,容易出错且乏味。为了解决这些问题,出现了大量“编译为 JS”的语言——Haskell 和 GHCJS 就是其中之一。