You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKit中如何在@html生成的HTML内实现动态字段替换?

问题描述

我想要创建一个Table组件,目前仅展示数据的功能正常,但还希望添加编辑/删除等动态标签。现有代码如下:

<script>
    
    const data = [
        {
            username: "Test 1"
        },
        {
            username: "Test 2"
        },
        {
            username: "Test 3"
        },
        {
            username: "Test 4"
        },
    ]
    
    const headers = [
        {
            key: 'username',
            text: 'Username'
        },
        {
            key: null,
            text: 'Reset Link',
            field: '<p>/users/reset/{user.username}</p>'
        }
    ];

</script>

<table>
    <tr>
        {#each headers as header}
            <th>{header.text}</th>
        {/each}
    </tr>

    {#each data as user}
        <tr>
            {#each headers as header}
                {#if user[header.key]}
                    <td>{user[header.key]}</td>
                {:else}
                    <td>{@html header.field}</td>
                {/if}
            {/each}
        </tr>
    {/each}
</table>

当前输出:

Username    Reset Link
Test 1          /users/reset/{user.username}
Test 2          /users/reset/{user.username}
Test 3          /users/reset/{user.username}
Test 4          /users/reset/{user.username}

预期输出:

Username    Reset Link
Test 1          /users/reset/Test 1
Test 2          /users/reset/Test 2
Test 3          /users/reset/Test 3
Test 4          /users/reset/Test 4

请问如何实现这类动态字段的替换?


解决方案

核心问题是header.field中的模板字符串只是普通文本,@html仅渲染HTML结构,不会处理变量替换。以下是几种可行的解决方法:

方法1:用模板函数替代静态字符串

把headers里的field改成接收user参数的函数,动态生成对应内容:

<script>
    const data = [
        { username: "Test 1" },
        { username: "Test 2" },
        { username: "Test 3" },
        { username: "Test 4" },
    ]
    
    const headers = [
        {
            key: 'username',
            text: 'Username'
        },
        {
            key: null,
            text: 'Reset Link',
            field: (user) => `<p>/users/reset/${user.username}</p>`
        }
    ];
</script>

<table>
    <tr>
        {#each headers as header}
            <th>{header.text}</th>
        {/each}
    </tr>

    {#each data as user}
        <tr>
            {#each headers as header}
                {#if header.key}
                    <td>{user[header.key]}</td>
                {:else}
                    <td>{@html header.field(user)}</td>
                {/if}
            {/each}
        </tr>
    {/each}
</table>

方法2:正则替换字符串变量

如果坚持用字符串格式的field,可以写工具函数替换{user.xxx}格式的变量:

<script>
    const data = [
        { username: "Test 1" },
        { username: "Test 2" },
        { username: "Test 3" },
        { username: "Test 4" },
    ]
    
    const replaceUserVars = (str, user) => {
        return str.replace(/\{user\.(\w+)\}/g, (match, key) => user[key] || match);
    }
    
    const headers = [
        {
            key: 'username',
            text: 'Username'
        },
        {
            key: null,
            text: 'Reset Link',
            field: '<p>/users/reset/{user.username}</p>'
        }
    ];
</script>

<table>
    <tr>
        {#each headers as header}
            <th>{header.text}</th>
        {/each}
    </tr>

    {#each data as user}
        <tr>
            {#each headers as header}
                {#if header.key}
                    <td>{user[header.key]}</td>
                {:else}
                    <td>{@html replaceUserVars(header.field, user)}</td>
                {/if}
            {/each}
        </tr>
    {/each}
</table>

方法3:用Svelte插槽实现(适合扩展编辑/删除功能)

如果后续要添加交互元素,插槽写法更符合Svelte特性,扩展性更强:

<!-- Table.svelte -->
<script>
    export let data;
    export let headers;
</script>

<table>
    <tr>
        {#each headers as header}
            <th>{header.text}</th>
        {/each}
    </tr>

    {#each data as user, index}
        <tr>
            {#each headers as header}
                {#if header.key}
                    <td>{user[header.key]}</td>
                {:else}
                    <td>
                        <slot name={header.slotName} {user} {index} />
                    </td>
                {/if}
            {/each}
        </tr>
    {/each}
</table>

使用组件时:

<script>
    import Table from './Table.svelte';
    const data = [
        { username: "Test 1" },
        { username: "Test 2" },
        { username: "Test 3" },
        { username: "Test 4" },
    ]
    
    const headers = [
        {
            key: 'username',
            text: 'Username'
        },
        {
            text: 'Reset Link',
            slotName: 'reset-link'
        },
        {
            text: 'Actions',
            slotName: 'actions'
        }
    ];

    const handleEdit = (user) => {
        console.log('编辑用户:', user);
    }

    const handleDelete = (user) => {
        console.log('删除用户:', user);
    }
</script>

<Table {data} {headers}>
    <div slot="reset-link" let:user>
        <p>/users/reset/{user.username}</p>
    </div>
    <div slot="actions" let:user>
        <button on:click={() => handleEdit(user)}>编辑</button>
        <button on:click={() => handleDelete(user)}>删除</button>
    </div>
</Table>

内容的提问来源于stack exchange,提问作者cunnus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 05:17:07