错误时更改 svelte 中 img 标签中的图像

Changing the image in an img tag in svelte upon error

我有一个关于如何在 Svelte 的#each 循环中处理图像错误的问题?

我正在构建一个界面,用户可以在其中 select 并通过访问由卡片组成的快速访问菜单在模块之间切换。

我的意图是在 quickAccessMenu 中触发 Title 2 上的错误,并通过函数 handleImgError 回退使用卡片的默认图像。但是我很难获得更改正在使用的图像的错误功能。

index.svelte

<script lang="ts">
    type quickAccessMenu = {
        "title": string;
        "image": string;
    }

    export const quickAccessMenu : quickAccessMenu[] = [
        { "title": "Menu Item 1", "image": "default.jpg" },
        { "title": "Menu Item 2", "image": "error.png" },
        { "title": "Menu Item 3", "image": "" }
    ];

    function handleImgError(i: number) {
        quickAccessMenu[i].image = "default.jpg";
    }
</script>

<div class="container">
    {#each quickAccessMenu as menu, i }
        <div class="small-card">
            <div class="card-bg-image">
                <p>{menu.title}</p>
                <div class="black-filter"></div>
                {
                    #if menu.image === "" 
                    || menu.image === null
                    || menu.image === undefined
                }
                    <img
                        src="/image/quick-access-menu/default.jpg"
                        alt="{menu.title} menu"
                    />
                {:else}
                    <img
                        src="/image/quick-access-menu/{menu.image}"
                        alt="{menu.title} menu"
                        on:error = {() => handleImgError(i)}
                    />
                {/if}
            </div>
        </div>
    {/each}
</div>

基本上是因为SSR的缘故没用。要修复它,您需要添加一个浏览器保护程序。

首先,导入 browser variable:

import { browser } from "$app/env"

然后在初始化时检查您是否在浏览器中 quickAccessMenu:

export const quickAccessMenu : quickAccessMenu[] = browser && [
    ...
];

script 标签的完整示例:

<script lang="ts">
    import { browser } from "$app/env";

    type quickAccessMenu = {
        "title": string;
        "image": string;
    }

    export const quickAccessMenu : quickAccessMenu[] = browser && [
        { "title": "Menu Item 1", "image": "default.jpg"},
        { "title": "Menu Item 2", "image": "error.png"},
        { "title": "Menu Item 3", "image": ""},
        { "title": "This should be an error", "image": "doesnt exist"},
    ];

    function handleImgError(i: number) {
        quickAccessMenu[i].image = "default.jpg";
    }
</script>

如果您不添加浏览器防护,on:error 事件实际上不会触发,令人惊讶。我不知道这是预期行为还是错误...



此外,作为建议,您可以使用 the new {@const ...} tag 来简化您的 HTML 标记,如下所示:

<div class="container">
    {#each quickAccessMenu as menu, i }
        {@const fileName = ["", null, undefined].includes(menu.image) ? 'default.jpeg' : menu.image}
        <div class="small-card">
            <div class="card-bg-image">
                <p>{menu.title}</p>
                <div class="black-filter"></div>
                <img
                    src="/image/quick-access-menu/{fileName}"
                    alt="{menu.title} menu"
                    on:error={() => handleImgError(i)}
                />
            </div>
        </div>
    {/each}
</div>

如果您不介意 0、空数组和空对象被解释为未定义(我怀疑您这样做),您甚至可以进一步简化对 {@const fileName = menu.image || 'default.jpg'} 的 const 赋值。