Svelte中DisplayEmail组件实现邮箱一行适配+剩余数量显示
Svelte DisplayEmail组件实现邮箱地址自动截断并显示剩余数量
我刚接触Svelte框架,希望在DisplayEmail组件中实现如下效果:一行内显示尽可能多的邮箱地址,无法容纳的邮箱以“剩余X个”的形式展示。要求仅修改DisplayEmail组件,不改动父组件代码。
现有父组件代码
<!-- Parent component --> <script lang="ts"> import DisplayEmail from 'components/DisplayEmail.svelte' const emailList = [ ['abc@yahoo.com', 'abc@hotmail.com', 'abc@hotmail.com', 'abc@gmail.com'], ] </script> <style lang="scss"> $border-style: solid 1px #777; table { table-layout: fixed; border: $border-style; width: 100%; text-align: left; } th, td { border: $border-style; padding: 5px 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; height: 34px; box-sizing: border-box; } th { &:nth-child(1) { width: 20%; } &:nth-child(2) { width: 30%; } &:nth-child(3) { width: 50%; } &:nth-child(4) { width: 90px; } &:nth-child(5) { width: 70px; } } tbody:nth-child(even) { background-color: #ddd; } .align-right { text-align: right; } </style> <table cellspacing="0"> <thead> <tr> <th>Sender</th> <th>Recipients</th> <th>Subject</th> <th class="align-right">Date</th> <th class="align-right">Time</th> </tr> </thead> <tbody> {#each emailList as emails} <tr> <td>demo@gmail.com</td> <td> <DisplayEmail {emails} /> </td> <td> Lorem ipsum dolor sit amet consectetur adipisicing elit. Enim, odio. </td> <td class="align-right">n/a</td> <td class="align-right">n/a</td> </tr> {/each} </tbody> </table>
现有DisplayEmail组件代码
<!--DisplayEmail Component --> <script lang="ts"> export let emails let showEmail = emails.map((email: string) => email) let spanWidth </script> <span bind:offsetWidth={spanWidth}>{showEmail}</span>
解决方案
修改DisplayEmail组件,通过动态测量容器与元素宽度,计算可容纳的邮箱数量,超出部分替换为剩余数量提示:
<!-- DisplayEmail Component --> <script lang="ts"> export let emails: string[]; let containerRef: HTMLElement; let measureRef: HTMLElement; let displayContent = ''; $: { if (emails.length === 0) { displayContent = ''; return; } setTimeout(() => { if (!containerRef || !measureRef) return; const containerWidth = containerRef.offsetWidth; // 测量单个邮箱(带分隔符)的宽度 measureRef.textContent = `${emails[0]}, `; const singleEmailWidth = measureRef.offsetWidth; // 测量剩余提示文本的宽度 measureRef.textContent = '剩余0个'; const remainingTipWidth = measureRef.offsetWidth; // 计算可容纳的邮箱数量,预留提示文本的空间 let maxShowCount = Math.floor((containerWidth - remainingTipWidth) / singleEmailWidth); maxShowCount = Math.max(1, maxShowCount); // 确保至少显示1个邮箱 if (maxShowCount >= emails.length) { displayContent = emails.join(', '); } else { const shownEmails = emails.slice(0, maxShowCount); const remaining = emails.length - maxShowCount; displayContent = `${shownEmails.join(', ')},剩余${remaining}个`; } }, 0); } </script> <div bind:this={containerRef} style="white-space: nowrap; overflow: hidden;"> {displayContent} </div> <!-- 隐藏的测量元素,用于计算文本宽度 --> <span bind:this={measureRef} style="visibility: hidden; position: absolute; top: 0; left: 0;" ></span>
关键说明
- 动态测量:用隐藏的
<span>测量单个邮箱(含分隔符)和剩余提示文本的宽度,保证计算精度。 - 响应式更新:通过Svelte的
$:反应式声明,在邮箱列表变化时自动重新计算显示内容。 - 边界处理:强制至少显示1个邮箱,避免容器过窄时无内容展示的情况。
- 样式适配:保持
white-space: nowrap确保内容不换行,overflow: hidden防止溢出容器。
内容的提问来源于stack exchange,提问作者Sakin
相关产品推荐
相关产品推荐

