Svelte 5/SvelteKit 2中动态导入SVG加密货币图标失效求助
问题:SvelteKit 2中动态导入加密货币SVG图标无法渲染
我正在使用Svelte 5/SvelteKit 2,从API获取的数据格式如下:
const itemsFromAPI = [ { id: 1, symbols: ['btc', 'eth'] }, { id: 2, symbols: ['xrp', 'xmr'] } ];
我希望通过加密货币图标库渲染每个符号对应的SVG图标(已知该库有Svelte版本但已5年未更新,因此不打算使用)。我编写了+page.svelte文件,但图标无法渲染,代码如下:
<script> const itemsFromAPI = [ { id: 1, symbols: ['btc', 'eth'] }, { id: 2, symbols: ['xrp', 'xmr'] } ]; const handleIconChange = async (iconName) => { return await import(`/node_modules/cryptocurrency-icons/svg/color/${iconName}.svg?inline`); }; </script> <h1>How to make dynamic crypto icons work here</h1> {#each itemsFromAPI as item (item.id)} <div> <span>{item.id}</span> {#each item.symbols as symbol (symbol)} <span>{symbol}</span> <span>{@html handleIconChange(symbol)}</span> {/each} </div> {/each}
解决方案
你的代码存在两个核心问题,以下是针对性的修正方案:
1. 修正动态导入逻辑与渲染方式
SvelteKit中,?inline导入SVG返回的是Svelte组件模块,而非直接可用的HTML字符串;且异步函数无法直接在{@html}中调用,必须配合{#await}块处理异步结果。推荐使用?raw后缀直接获取SVG文本内容,再通过{@html}渲染:
修正后的基础版本代码
<script> const itemsFromAPI = [ { id: 1, symbols: ['btc', 'eth'] }, { id: 2, symbols: ['xrp', 'xmr'] } ]; async function getSvgContent(symbol) { try { // 省略/node_modules/前缀,SvelteKit会自动从依赖中查找 const module = await import(`cryptocurrency-icons/svg/color/${symbol}.svg?raw`); return module.default; } catch (err) { console.error(`加载图标 ${symbol} 失败:`, err); return ''; } } </script> <h1>动态加密货币图标渲染示例</h1> {#each itemsFromAPI as item (item.id)} <div> <span>{item.id}</span> {#each item.symbols as symbol (symbol)} <span>{symbol}</span> <!-- 用{#await}处理异步获取的SVG内容 --> {#await getSvgContent(symbol)} <span>加载中...</span> {:then svgContent} <span>{@html svgContent}</span> {:catch} <span>图标加载失败</span> {/await} {/each} </div> {/each}
2. 优化方案:预加载图标减少异步请求
如果API返回的符号数量不多或可提前预知,可以预加载所有需要的图标,避免多次异步请求:
<script> const itemsFromAPI = [ { id: 1, symbols: ['btc', 'eth'] }, { id: 2, symbols: ['xrp', 'xmr'] } ]; // 缓存已加载的SVG内容 const svgCache = {}; // 页面初始化时预加载所有需要的图标 async function preloadIcons() { const allSymbols = itemsFromAPI.flatMap(item => item.symbols); for (const symbol of allSymbols) { if (!svgCache[symbol]) { const module = await import(`cryptocurrency-icons/svg/color/${symbol}.svg?raw`); svgCache[symbol] = module.default; } } } preloadIcons(); </script> <h1>预加载加密货币图标示例</h1> {#each itemsFromAPI as item (item.id)} <div> <span>{item.id}</span> {#each item.symbols as symbol (symbol)} <span>{symbol}</span> {#if svgCache[symbol]} <span>{@html svgCache[symbol]}</span> {:else} <span>加载中...</span> {/if} {/each} </div> {/each}
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

