转换 Html DOM
Transform Html DOM
我是 Elm 的新手,到目前为止我真的很喜欢它,但是我 运行 遇到了一个我似乎无法解决的问题。
我有一个HtmlDOM,例如
div []
[ h1 [] [text "Headline 1"]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"]
]
我想在每个 h[1-6] 元素中添加 a-links 并将其转换为类似(保持简单)
div []
[ h1 [] [ text "Headline 1"
, [a [name "headline"] [text "#"]
]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"
, [a [name "headline"] [text "#"]
]
]
这在概念上并不难。查看DOM,如果元素是h[1-6],添加一个a-link作为子元素。然而,我对 Elm 的理解还不足以让它工作。
这是我到目前为止一直在尝试的方法。
transform : Html a -> Html a
transform node =
-- check if the tag is h1-h6
case node.tag of
-- add a-link to h1 children
"h1" -> { node | children = (a [name "headline"] [text "#") :: node.children }
"h2" -> { node | children = (a [name "headline"] [text "#") :: node.children }
-- do this for all nodes in the tree
_ -> { node | children = List.map transform node.children }
这行不通。
The type annotation for `transform` does not match its definition.
40| transform : Html a -> Html a
^^^^^^^^^^^^^^^^
The type annotation is saying:
VirtualDom.Node a -> VirtualDom.Node a
But I am inferring that the definition has this type:
{ b | tag : String, children : List (Html a) }
-> { b | children : List (Html a), tag : String }
我知道我不能 node.tag
因为通用类型 a
可能没有那个字段。它不会是类型安全的。例如,文本节点没有标签字段,但仍然是 Html.Html a
.
的实例
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a
我的问题是,我该怎么做?我可以这样做吗?还是我不应该这样做?
无法修改 Html msg
类型的现有值。
它们是最终的内部结构,由 Virtual DOM 渲染到实际的 HTML 节点中作为程序的输出。
Html msg
是 VirtualDom.Node a
的别名
您正试图将它们用作记录,但那只是一个 JavaScript 对象。
Elm REPL 在此处输出抽象数据结构的字符串表示:
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a -- not a record
与其尝试转换 Html msg -> Html msg
,不如尝试这样的操作:
-- Input example: [ "#", "http://google.com/", "http://package.elm-lang.org/" ]
linksView : List String -> Html msg
linksView links =
links
|> List.map (\link -> a [ href link ] [ text link ])
|> div [] -- Expected output: <div> with thre links
在 Elm 中,Html a
实际上只用作输出。您永远不会像 transform
函数尝试的那样将其用作输入。
创建一个模型来描述您的域,然后将其传递给 view
函数以呈现 html。
会更好地为您服务
type alias Article =
{ priority : Priority
, headline : String
, body : String
}
type alias Model =
List Article
type Priority = First | Second
您的视图可能如下所示:
view : Model -> Html msg
view =
div [] << List.map viewArticle
viewArticle : Article -> Html msg
viewArticle article =
let
priorityTag =
case article.priority of
First -> h1
Second -> h2
in
div []
[ priorityTag []
[ text article.headline
, a [ name "headline" ] [ text "#" ]
]
, p [] [ text article.body ]
]
我是 Elm 的新手,到目前为止我真的很喜欢它,但是我 运行 遇到了一个我似乎无法解决的问题。
我有一个HtmlDOM,例如
div []
[ h1 [] [text "Headline 1"]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"]
]
我想在每个 h[1-6] 元素中添加 a-links 并将其转换为类似(保持简单)
div []
[ h1 [] [ text "Headline 1"
, [a [name "headline"] [text "#"]
]
, p [] [text "Some text"]
, h2 [] [text "Headline 2"
, [a [name "headline"] [text "#"]
]
]
这在概念上并不难。查看DOM,如果元素是h[1-6],添加一个a-link作为子元素。然而,我对 Elm 的理解还不足以让它工作。
这是我到目前为止一直在尝试的方法。
transform : Html a -> Html a
transform node =
-- check if the tag is h1-h6
case node.tag of
-- add a-link to h1 children
"h1" -> { node | children = (a [name "headline"] [text "#") :: node.children }
"h2" -> { node | children = (a [name "headline"] [text "#") :: node.children }
-- do this for all nodes in the tree
_ -> { node | children = List.map transform node.children }
这行不通。
The type annotation for `transform` does not match its definition.
40| transform : Html a -> Html a
^^^^^^^^^^^^^^^^
The type annotation is saying:
VirtualDom.Node a -> VirtualDom.Node a
But I am inferring that the definition has this type:
{ b | tag : String, children : List (Html a) }
-> { b | children : List (Html a), tag : String }
我知道我不能 node.tag
因为通用类型 a
可能没有那个字段。它不会是类型安全的。例如,文本节点没有标签字段,但仍然是 Html.Html a
.
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a
我的问题是,我该怎么做?我可以这样做吗?还是我不应该这样做?
无法修改 Html msg
类型的现有值。
它们是最终的内部结构,由 Virtual DOM 渲染到实际的 HTML 节点中作为程序的输出。
Html msg
是 VirtualDom.Node a
您正试图将它们用作记录,但那只是一个 JavaScript 对象。
Elm REPL 在此处输出抽象数据结构的字符串表示:
> text "Hello World"
{ type = "text", text = "Hello World" } : Html.Html a -- not a record
与其尝试转换 Html msg -> Html msg
,不如尝试这样的操作:
-- Input example: [ "#", "http://google.com/", "http://package.elm-lang.org/" ]
linksView : List String -> Html msg
linksView links =
links
|> List.map (\link -> a [ href link ] [ text link ])
|> div [] -- Expected output: <div> with thre links
在 Elm 中,Html a
实际上只用作输出。您永远不会像 transform
函数尝试的那样将其用作输入。
创建一个模型来描述您的域,然后将其传递给 view
函数以呈现 html。
type alias Article =
{ priority : Priority
, headline : String
, body : String
}
type alias Model =
List Article
type Priority = First | Second
您的视图可能如下所示:
view : Model -> Html msg
view =
div [] << List.map viewArticle
viewArticle : Article -> Html msg
viewArticle article =
let
priorityTag =
case article.priority of
First -> h1
Second -> h2
in
div []
[ priorityTag []
[ text article.headline
, a [ name "headline" ] [ text "#" ]
]
, p [] [ text article.body ]
]