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

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>

关键说明

  1. 动态测量:用隐藏的<span>测量单个邮箱(含分隔符)和剩余提示文本的宽度,保证计算精度。
  2. 响应式更新:通过Svelte的$:反应式声明,在邮箱列表变化时自动重新计算显示内容。
  3. 边界处理:强制至少显示1个邮箱,避免容器过窄时无内容展示的情况。
  4. 样式适配:保持white-space: nowrap确保内容不换行,overflow: hidden防止溢出容器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:24:48