我最近想使用 Vue3 构建一个像 Gmail 一样的收件人列表,但我不知道如何实现这一点,而且我似乎无法在网上找到好的资源。
我有一个包含电子邮件的字符串数组,我可以循环它们以将它们显示在 div 中。但我怎么知道何时到达 div 的末尾并且我必须删除电子邮件?
然后,每封隐藏的电子邮件都会被计数并显示为徽章。当然,如果所有电子邮件都装在框中,则不会显示徽章。
谢谢您的指导!
我还没有尝试任何事情,因为我什至不知道从哪里开始。 我应该获取容器 div 的宽度,但是我如何知道包含电子邮件的子 div 何时到达父级的末尾?
首先测量电子邮件容器的宽度。随后,只要电子邮件数组或浏览器宽度发生变化,就会测量每个电子邮件元素。此测量调整电子邮件数组(使用
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>