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

如何在Vue3中实现类Gmail的收件人列表(带隐藏计数徽章)

Vue3 实现类似Gmail的收件人列表方案

核心思路

通过获取容器与子元素的实际尺寸,动态计算可显示的收件人数量,超出部分隐藏后用徽章统计剩余数量。

步骤实现

1. 基础布局搭建

先完成结构与样式,父容器用flex实现横向排列,收件人项统一样式,徽章默认隐藏:

<template>
  <div ref="container" class="recipient-container">
    <div 
      v-for="(email, index) in visibleEmails" 
      :key="index" 
      class="recipient-item"
    >
      {{ email }}
    </div>
    <div v-if="hiddenCount > 0" class="badge">+{{ hiddenCount }}</div>
  </div>
</template>

<style scoped>
.recipient-container {
  display: flex;
  flex-wrap: nowrap;
  overflow: hidden;
  padding: 4px;
  border: 1px solid #ddd;
  border-radius: 4px;
}
.recipient-item {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  margin-right: 6px;
  background: #f1f3f4;
  border-radius: 16px;
  font-size: 14px;
}
.badge {
  display: inline-flex;
  align-items: center;
  padding: 4px 8px;
  background: #f1f3f4;
  border-radius: 16px;
  font-size: 14px;
}
</style>

2. 动态计算逻辑实现

用Vue3的ref获取DOM元素,在组件挂载和窗口 resize 时执行尺寸计算:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

// 模拟你的邮箱数组
const emails = ref(['user1@example.com', 'user2@example.com', 'user3@example.com', 'user4@example.com', 'user5@example.com'])
const container = ref(null)
const visibleEmails = ref([])
const hiddenCount = ref(0)
let resizeTimer = null

// 计算可显示的收件人数量
const calculateVisibleItems = () => {
  if (!container.value) return
  
  const containerWidth = container.value.clientWidth
  const badge = container.value.querySelector('.badge')
  const badgeWidth = badge ? badge.offsetWidth + 6 : 0 // 加上徽章的间距
  const items = container.value.querySelectorAll('.recipient-item')
  
  let totalWidth = 0
  let visibleCount = 0
  
  for (let i = 0; i < items.length; i++) {
    const itemWidth = items[i].offsetWidth + 6 // 加上收件人项的右侧间距
    // 预留徽章宽度,避免最后一项与徽章挤压
    if (totalWidth + itemWidth + badgeWidth <= containerWidth) {
      totalWidth += itemWidth
      visibleCount++
    } else {
      break
    }
  }
  
  visibleEmails.value = emails.value.slice(0, visibleCount)
  hiddenCount.value = emails.value.length - visibleCount
}

onMounted(() => {
  calculateVisibleItems()
  // 监听窗口 resize,防抖减少计算次数
  window.addEventListener('resize', () => {
    clearTimeout(resizeTimer)
    resizeTimer = setTimeout(calculateVisibleItems, 100)
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', () => {
    clearTimeout(resizeTimer)
  })
})
</script>

3. 动态更新处理

如果收件人是动态添加/删除的,在数据变更后重新执行计算:

// 示例:添加新邮箱的方法
const addEmail = (newEmail) => {
  emails.value.push(newEmail)
  // 等待DOM更新后再计算
  setTimeout(calculateVisibleItems, 0)
}

关键注意点

  • 尺寸计算要完整:需把元素的margin、padding都纳入计算,避免出现显示偏差。
  • 防抖优化:窗口 resize 时用防抖减少重复计算,提升页面性能。
  • DOM更新时机:动态修改邮箱数组后,要等DOM渲染完成再执行计算,可通过setTimeout或nextTick实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:52:40