需要一些想法来在 Vue3 中构建类似 Gmail 的收件人列表

问题描述 投票:0回答:1

我最近想使用 Vue3 构建一个像 Gmail 一样的收件人列表,但我不知道如何实现这一点,而且我似乎无法在网上找到好的资源。

recipient list

我有一个包含电子邮件的字符串数组,我可以循环它们以将它们显示在 div 中。但我怎么知道何时到达 div 的末尾并且我必须删除电子邮件?

然后,每封隐藏的电子邮件都会被计数并显示为徽章。当然,如果所有电子邮件都装在框中,则不会显示徽章。

谢谢您的指导!

我还没有尝试任何事情,因为我什至不知道从哪里开始。 我应该获取容器 div 的宽度,但是我如何知道包含电子邮件的子 div 何时到达父级的末尾?

javascript arrays vue.js vuejs3 gmail
1个回答
0
投票

首先测量电子邮件容器的宽度。随后,只要电子邮件数组或浏览器宽度发生变化,就会测量每个电子邮件元素。此测量调整电子邮件数组(使用

slice()
),确保切片电子邮件适合电子邮件容器 div。

您可以运行我制作的这个示例:

const app = Vue.createApp({
  data() {
    return {
      emails: [],
      renderedEmails: [],
      hiddenCount: 0,
    }
  },
  methods: {
    measureRecipientList() {
      const tolerance = 50
      const containerWidth =
        document.getElementById('email-container').offsetWidth + tolerance
      let totalWidth = 0
      let countDisplay = -1
      setTimeout(() => {
        const hiddenEmailDivs =
          document.getElementsByClassName('hidden-email')
        for (const el of hiddenEmailDivs) {
          if (totalWidth < containerWidth) {
            totalWidth += el.clientWidth
            countDisplay += 1
          }
        }
        if (totalWidth > containerWidth) {
          countDisplay -= 1
        }
        this.renderedEmails = this.emails.slice(0, countDisplay)
        this.hiddenCount = this.emails.length - countDisplay
      })
    },
    onWidthChange() {
      this.measureRecipientList()
    }
  },
  mounted() {
    window.addEventListener("resize", this.onWidthChange);
    setTimeout(() => {
      this.emails = [
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
        '[email protected]',
      ]
    }, 500) // simulate loading 500 ms
  },
  unmounted() {
    window.removeEventListener("resize", this.onWidthChange);
  },
  watch: {
    emails() {
      this.measureRecipientList()
    },
  },
})
  
app.mount("#app")
#email-container {
  border: 1px solid #ccc;
  padding: 2px;
  height: 25px;
  white-space: nowrap;
  position: relative;
  overflow-x: hidden;
}

.email {
  opacity: 1;
  display: inline-block;
  border: 1px solid #ccc;
  background-color: pink;
  padding: 2px 2px;
  border-radius: 6px;
}

.hidden-email {
  visibility: hidden;
  display: inline-block;
  border: 1px solid #ccc;
  background-color: pink;
  padding: 2px 2px;
  margin-right: 2px;
  border-radius: 6px;
}

#badge {
  background-color: red;
  color: white;
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100px;
}
<div id="app">
<div>Recipient List:</div>
  <div id="email-container">
    <div class="email" v-for="(email, index) in renderedEmails" :key="index">
      {{ email }}
    </div>
    <div class="hidden-email" v-for="(email, index) in emails" :key="index">
      {{ email }}
    </div>
    <div id="badge">
      {{ hiddenCount }} more
    </div>
  </div>  
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.8/vue.global.min.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.