Elm:属性"onerror"改为添加"data-onerror"属性

The*_*ler 10 elm

在Elm中,我有一个简单的图像,我希望它被一些"缺失"的图像所取代.所以我添加了一个"onerror"属性:

img
    [ src "broken-link.png"
    , attribute "onerror" "this.onerror=null;this.src='missing.png';"
    ] []
Run Code Online (Sandbox Code Playgroud)

但是,当我查看生成的html时,img没有得到onerror属性,而是得到一个data-onerror,而且当然这不起作用.

为什么是这样?我该如何解决?

以下是我与朋友Bulbasaur一起举例说明问题的一个小例子:https://ellie-app.com/3Yn8Y6Rmvrqa1

Mar*_*ire 13

为什么是这样?

这似乎是Elm的内置无证安全功能.

检查Elm的源代码,Html.attribute定义为()

attribute : String -> String -> Attribute msg
attribute =
    VirtualDom.attribute
Run Code Online (Sandbox Code Playgroud)

VirtualDom.attribute定义为(来源):

attribute : String -> String -> Attribute msg
attribute key value =
    Elm.Kernel.VirtualDom.attribute
        (Elm.Kernel.VirtualDom.noOnOrFormAction key)
        (Elm.Kernel.VirtualDom.noJavaScriptOrHtmlUri value)
Run Code Online (Sandbox Code Playgroud)

您的属性名称onclick将传递到Elm.Kernel.VirtualDom.noOnOrFormActionJavaScript中定义为():

function _VirtualDom_noOnOrFormAction(key)
{
    return /^(on|formAction$)/i.test(key) ? 'data-' + key : key;
}
Run Code Online (Sandbox Code Playgroud)

因此,如果属性名称以on字符串开头,或者是字符串formAction,则将其重命名为数据属性.

我如何解决它?

我知道如何解决这个问题的一种方法是在没有JavaScript的情况下在Elm中编写代码.这是完整的工作示例,下面复制了主要部分:(这是基于此处关于检测图像加载失败的已接受答案.)

1)在模型中保留当前URL

type alias Model =
    { src : String
    }

init : Model
init =
    { src = "http://example.com" }
Run Code Online (Sandbox Code Playgroud)

2)更改事件处理程序以在图像加载错误时发送Elm消息

img
    [ src model.src
    , on "error" (Json.Decode.succeed ImageError)
    , alt "Should be Bulbasaur"
    ] []
Run Code Online (Sandbox Code Playgroud)

3)update在出错时更改URL

update : Msg -> Model -> Model
update msg model =
    case msg of
        ImageError ->
            { model
                | src = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png"
            }
Run Code Online (Sandbox Code Playgroud)


Aru*_*hit 7

我通过为图像加载错误事件编写自定义事件处理程序来解决此问题.自定义处理程序将如下所示:

onImageLoadError : msg -> Html.Attribute msg
onImageLoadError message =
    on "error" (JD.succeed message)
Run Code Online (Sandbox Code Playgroud)

我将定义的Model,Msg如下图所示:

type Msg
    = ImageLoadError


type alias Model =
    ImageSrc
Run Code Online (Sandbox Code Playgroud)

我还将定义一个自定义类型来包装好的和默认的URL.

type ImageSrc
    = Good String
    | Default String
Run Code Online (Sandbox Code Playgroud)

onImageLoadError将被解雇并发送ImageLoadError味精的update功能,并且update然后函数将设置默认的网址为:

update : Msg -> Model -> Model
update msg model =
    case msg of
        ImageLoadError ->
            Default "https://developer.mozilla.org/static/img/web-docs-sprite.22a6a085cf14.svg"
Run Code Online (Sandbox Code Playgroud)

这是完整的可运行代码:

module Main exposing (main)

import Browser
import Html exposing (Html, div, img, text)
import Html.Attributes exposing (alt, src)
import Html.Events exposing (on)
import Json.Decode as JD


type Msg
    = ImageLoadError


type ImageSrc
    = Good String
    | Default String


type alias Model =
    ImageSrc


update : Msg -> Model -> Model
update msg model =
    case msg of
        ImageLoadError ->
            Default "https://developer.mozilla.org/static/img/web-docs-sprite.22a6a085cf14.svg"


imageSrcVal : ImageSrc -> String
imageSrcVal src =
    case src of
        Good url ->
            url

        Default url ->
            url


view : Model -> Html Msg
view model =
    div []
        [ div [] [ text "Broken image, that should be replaced by Bulbasaur: " ]
        , img
            [ src (imageSrcVal model)
            , alt "Should be Bulbasaur"
            , onImageLoadError ImageLoadError
            ]
            []
        , div [] [ text "instead it does nothing, and the 'onerror' attribute is 'data-onerror' (use inspect element to see)" ]
        ]


onImageLoadError : msg -> Html.Attribute msg
onImageLoadError message =
    on "error" (JD.succeed message)


main : Program () Model Msg
main =
    Browser.sandbox
        { init = Good "https://developer.mozilla.org/static/arrows/arrow-right.cbc8b4f075cc.svg"
        , view = view
        , update = update
        }
Run Code Online (Sandbox Code Playgroud)

艾莉App.

初始化一个模型良好的 URL" https://developer.mozilla.org/static/arrows/arrow-right.cbc8b4f075cc.svg ",但如果你以某种方式让一个坏的网址,如" HTTPS://bad.developer .mozilla.org/static/arrows/arrow-right.cbc8b4f075cc.svg ",你将在那里找到默认图像.