Как преобразовать компоненты purescript-halogen в тег <head>
Как я могу отобразить определенный компонент Purescript-галоген в тег
?Следующий пример, написанный для Halogen 1.0.0, отображает таблицу стилей и абзац в тело HTML:
module Main where
import Prelude
import Control.Monad.Eff (Eff)
import Data.Maybe (Maybe(Nothing))
import CSS as C
import Halogen as H
import Halogen.Aff as HA
import Halogen.HTML as HH
import Halogen.HTML.CSS as HS
import Halogen.Query.HalogenM as HQ
import Halogen.VDom.Driver as HV
styles :: forall p i. HH.HTML p i
styles = HS.stylesheet $
C.select C.body $ C.margin C.nil C.nil C.nil C.nil
content :: forall p i. HH.HTML p i
content = HH.p_ [ HH.text "Test" ]
main :: Eff (HA.HalogenEffects ()) Unit
main = HA.runHalogenAff $ HA.awaitBody >>= HV.runUI ui unit
where
ui = H.component { initialState : const unit
, render : const render
, eval : const $ HQ.halt "no query"
, receiver : const Nothing
}
render = HH.div_ [ styles, content ]
DOM генерируется следующим образом:
<html>
<head>
<title>Test</title>
<script async="" type="text/javascript" src="main.js"></script>
</head>
<body>
<div>
<style type="text/css">
body { margin: 0 0 0 0 }
</style>
<p>
Test
</p>
</div>
</body>
</html>
Этот пример работает, но в соответствии со спецификацией элемент стиля допускается только "там, где ожидается содержание метаданных", то есть элемент
. Поэтому я хочу сделать там таблицу стилей. Как мне это сделать?1 ответ
Обратите внимание на awaitBody
функция - а также в ожидании загрузки, это выбирает body
элемент, который не совсем то, что вы хотите в этом случае. Если вы хотите написать в head
тогда вам нужно будет выбрать это и передать его runUI
для компонента, который отображает таблицу стилей.
Вам также нужно будет запустить два отдельных компонента, один для head
один для body
:
module Main where
import Prelude
import Control.Monad.Aff.Console (CONSOLE)
import Control.Monad.Eff (Eff)
import Data.Const (Const)
import Data.Foldable (traverse_)
import Data.Maybe (Maybe(..))
import Data.Newtype (unwrap)
import Halogen as H
import Halogen.Aff as HA
import Halogen.HTML as HH
import Halogen.VDom.Driver (runUI)
bodyComponent :: forall m. H.Component HH.HTML (Const Void) Unit Void m
bodyComponent =
H.component
{ initialState: const unit
, render: const $ HH.div_ [ HH.text "A component" ]
, eval: absurd <<< unwrap
, receiver: const Nothing
}
styleComponent :: forall m. H.Component HH.HTML (Const Void) Unit Void m
styleComponent =
H.component
{ initialState: const unit
, render: const $ HH.style_ [ HH.text "body { background: #222; color: #eee }"]
, eval: absurd <<< unwrap
, receiver: const Nothing
}
main :: Eff (HA.HalogenEffects (console :: CONSOLE)) Unit
main = HA.runHalogenAff do
HA.awaitLoad
traverse_ (runUI styleComponent unit) =<< HA.selectElement "head"
traverse_ (runUI bodyComponent unit) =<< HA.selectElement "body"
Если им нужно общаться, то вы можете использовать subscribe
а также driver
функции от HalogenIO
записать что runUI
производит для установки каналов между ними.
У меня были опасения по поводу этого, так как вы должны пройти через элемент, который пуст в качестве цели для контейнера, который будет отображаться... но при использовании Halogen-предоставляемых VDom
водитель, по-видимому, ведет себя по крайней мере, в том, что <head>
содержимое не будет заменено компонентом стиля (он добавляется в конец). Это в основном неопределенное поведение, так что я не уверен, что это будет справедливо для других драйверов.