Core concepts
The View DSL
A VNode represents a DOM element — the most common kind of virtual DOM node. It carries a Namespace, a tag name, a list of Attribute values and a list of child Views.
The View type
The View is a rose tree of nodes, mutually recursive with Component through view:
data View context props model action
= VNode Namespace Tag [Attribute model action] [View context props model action] DirectEvents
| VText (Maybe Key) MisoString
| VComp (SomeComponent context)
| forall childProps. VCompStatic (StaticPtr (SomeStaticComponent childProps context)) childProps
| VFrag (Maybe Key) [View context props model action]
| VContext (context -> View context props model action)
| VProps (props -> View context props model action)
| VModel (model -> View context props model action)
data SomeComponent context
= forall model action props. (Eq context, Eq model, Eq props)
=> SomeComponent (Maybe Key) props (Component context props model action)VNode and VText map one-to-one onto the physical DOM. VComp and VFrag are abstract (they live only in the virtual DOM). The existential SomeComponent is what allows embedding polymorphic components in a View. VCompStatic carries a static pointer to its constructor and is used by the native dual-thread runtime.
VContext, VProps and VModel are not nodes at all, but accessors. Each wraps a function from the app-global context, the enclosing component's props or its model to a View. The function is applied and the wrapper discarded when the enclosing View is built or rendered, so none of the three ever reaches the diff. Build them with vcontext, vprops and vmodel — see Ambient accessors.
Element nodes
VNode HTML "div" [ HP.id_ "container" ] [ "Hello, world!" ]In practice you rarely construct VNode directly. Use the element smart constructors from Miso.Html.Element, which fix the namespace and tag for you:
H.div_ [ HP.id_ "container" ] [ "Hello, world!" ]
H.button_ [ HE.onClick DoSomething ] [ "Click me" ]
H.h1_ [ HP.className "title" ] [ text (ms pageTitle) ]For elements not covered by Miso.Html.Element, use node (or its synonym vnode) directly:
node HTML "details" []
[ node HTML "summary" [] [ "More info" ] ]SVG and MathML elements use the SVG and MATHML namespaces and are covered by Miso.Svg.Element and Miso.Mathml.Element. Unlike VComp and VFrag, a VNode has a one-to-one correspondence with a physical DOM element.
node- raw constructor — namespace, tag, attributes, children
vnode- synonym for
node Miso.Html.Element- every HTML element (
div_,span_,input_…) Miso.Svg.Element- SVG graphics, animation and container elements
Miso.Mathml.Element- MathML elements
Lifecycle hooks
Like components, elements expose lifecycle hooks:
onBeforeCreatedonCreated/onCreatedWithonBeforeDestroyed/onBeforeDestroyedWithonDestroyed
These are useful for initialising and tearing down third-party libraries, as in this example using highlight.js:
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE MultilineStrings #-}
import Miso
import Miso.FFI.QQ (js)
data Action = Highlight DOMRef
update
:: Action
-> Effect context props model Action
update = \case
Highlight domRef ->
io_ [js| hljs.highlightElement(${domRef}) |]
view
:: model
-> View context props model Action
view _ =
H.code_ [ onCreatedWith Highlight ]
[ """
function addOne (x) { return x + 1; }
"""
]As a convention, the *With variant of a lifecycle hook (e.g. onCreatedWith) provides the target DOMRef to the callback.
The smart constructors, at a glance
node, vnode- build a
VNode text, vtext- build a
VText— see Text nodes component- build a
VComp fragment, vfrag, fragment_, vfrag_- build a
VFrag (+>)- key and mount a child
Component vcontext, vprops, vmodel- build a
VContext,VPropsorVModel— see Ambient accessors