首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用榆树0.19创建SPA?

如何用榆树0.19创建SPA?
EN

Stack Overflow用户
提问于 2018-09-27 20:36:02
回答 2查看 1.3K关注 0票数 1

我试图建立一个SPA与榆树和创建三个页面,应该显示的内容,取决于URL。

这三页的内容相似,例如Page.elm

代码语言:javascript
复制
module Page.NotFound exposing (Msg(..), content)

import Html exposing (..)
import Html.Attributes exposing (..)



---- UPDATE ----


type Msg
    = NotFoundMsg


content : Html Msg
content =
    p [] [ text "Sorry can not find page." ]

Main.elm中,我有以下代码:

代码语言:javascript
复制
module Main exposing (Model, Msg(..), init, main, update, view)

import API.Keycloak as Keycloak exposing (..)
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Json.Decode as Decode
import Page.Account as Account
import Page.Home as Home
import Page.NotFound as NotFound
import Route
import Url
import Url.Parser exposing ((</>), Parser, int, map, oneOf, parse, s, string)



---- MODEL ----


type alias Model =
    { key : Nav.Key
    , url : Url.Url
    , auth : Result String Keycloak.Struct
    }


init : Decode.Value -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
    ( Model key url (Keycloak.validate flags), Cmd.none )



---- ROUTE ----


type Route
    = Account



---- UPDATE ----


type Msg
    = PageNotFound NotFound.Msg
    | PageAccount Account.Msg
    | PageHome Home.Msg
    | LinkClicked Browser.UrlRequest
    | UrlChanged Url.Url


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        LinkClicked urlRequest ->
            case urlRequest of
                Browser.Internal url ->
                    ( model, Nav.pushUrl model.key (Url.toString url) )

                Browser.External href ->
                    ( model, Nav.load href )

        UrlChanged url ->
            ( { model | url = url }
            , Cmd.none
            )



-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions _ =
    Sub.none



---- VIEW ----


info : Html Msg
info =
    header [] [ text "Header" ]


createLink : String -> Html Msg
createLink path =
    a [ href ("/" ++ path) ] [ text path ]


navigation : Html Msg
navigation =
    ul []
        [ li [] [ createLink "home" ]
        , li [] [ createLink "account" ]
        ]


content : Model -> Html Msg
content model =
    main_ []
        [ case parse Route.parser model.url of
            Just path ->
                matchedRoute path

            Nothing ->
                NotFound.content
        ]


matchedRoute : Route.Route -> Html Msg
matchedRoute path =
    case path of
        Route.Home ->
            Home.content

        Route.Account ->
            Account.content


body : Model -> List (Html Msg)
body model =
    [ info
    , navigation
    , content model
    ]


view : Model -> Browser.Document Msg
view model =
    { title = "Cockpit"
    , body = body model
    }



---- PROGRAM ----


main : Program Decode.Value Model Msg
main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = subscriptions
        , onUrlChange = UrlChanged
        , onUrlRequest = LinkClicked
        }

编译器抱怨:

代码语言:javascript
复制
-- TYPE MISMATCH -------------- /home/developer/Desktop/elm/cockpit/src/Main.elm

The 2nd branch of this `case` does not match all the previous branches:

104|         [ case parse Route.parser model.url of
105|             Just path ->
106|                 matchedRoute path
107|
108|             Nothing ->
109|                 NotFound.content
                     ^^^^^^^^^^^^^^^^
This `content` value is a:

    Html NotFound.Msg

But all the previous branches result in:

    Html Msg

Hint: All branches in a `case` must produce the same type of values. This way,
no matter which branch we take, the result is always a consistent shape. Read
<https://elm-lang.org/0.19.0/union-types> to learn how to “mix” types.

-- TYPE MISMATCH -------------- /home/developer/Desktop/elm/cockpit/src/Main.elm

Something is off with the 2nd branch of this `case` expression:

120|             Account.content
                 ^^^^^^^^^^^^^^^
This `content` value is a:

    Html Account.Msg

But the type annotation on `matchedRoute` says it should be:

    Html Msg

-- TYPE MISMATCH -------------- /home/developer/Desktop/elm/cockpit/src/Main.elm

Something is off with the 1st branch of this `case` expression:

117|             Home.content
                 ^^^^^^^^^^^^
This `content` value is a:

    Html Home.Msg

But the type annotation on `matchedRoute` says it should be:

    Html Msg
Detected errors in 1 module.

我知道这种类型是错误的,但不知道如何证明它。

我怎么才能让它起作用?

我还看了https://github.com/rtfeldman/elm-spa-example/blob/master/src/Main.elm的例子,但不知道它是如何工作的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-28 01:04:32

您有多个Msg类型,这是可以的,但它可能会导致混淆。简而言之:Main.MsgNotFound.Msg的类型不同。

函数matchedRoute返回一个Html Main.Msg,而函数NotFound.content返回一个Html NotFound.Msg;类型完全不同。

您已经完成了99%的工作,因为您有一个PageNotFound NotFound.Msg类型的构造函数,它生成一个Main.Msg。这允许您将NotFound.Msg包装在Main.Msg中。这应该是在您的PageNotFound NotFound.content分支中执行Nothing ->的问题。

票数 2
EN

Stack Overflow用户

发布于 2018-10-13 16:51:02

问题是,NotFound.content引用的NotFound.content类型是NotFound.MsgMain.matchedRoute引用的Msg类型是Main.Msg,而这些类型并不是自动统一的。因此,当您在case表达式的不同分支中使用它们时,编译器会告诉您,它们是不同的,不能统一为单个类型,以便case表达式返回。

因此,您必须将其中一个转换为另一个,通常的方法是在“外部”msg类型(Main.Msg)中添加一个变体,它包装了“内部”msg类型(NotFound.Msg)。幸运的是,您已经将该变体添加为PageNotFound NotFound.Msg,因此我们可以继续前进。

下一步是在NotFound.Msgs中完成PageNotFound的包装,不幸的是,我们很少单独处理NotFound.Msg的值,它通常被包装在其他类型中,比如HtmlCmd,这是比较棘手的。幸运的是,Evan有足够的预见性来预测这种情况,并为我们添加了Cmd.mapHtml.map供我们使用。就像List.mapMaybe.map一样,Cmd.mapHtml.map接受一个函数a -> b,并使用它分别将Html as或Cmd as转换为Html bs或Cmd bs。

所以,您真正需要做的就是在Html.map上使用PageNotFound on NotFound.content

代码语言:javascript
复制
content : Model -> Html Msg
content model =
    main_ []
        [ case parse Route.parser model.url of
            Just path ->
                matchedRoute path

            Nothing ->
                NotFound.content |> Html.map PageNotFound
        ]

这两个分支现在都将返回Main.Msg,编译器应该很高兴:)

顺便说一句,在elm-spa-例中,这是这里做的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52544763

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档