元素不定大小隐藏做溢出隐藏
刀刀
0字
0分钟
2026/8/16
学习目标
- 需求效果的实现
- JavaScript能力锻炼
- IntersectionObserver 的使用
思路分析

效果实现思路主要是找到最后一个显示在容器内的DOM元素,计算它后面的个数,加上它自己本身,然后隐藏后面的元素并显示 +n (n 为隐藏的元素个数 + 最后一个元素)。
假设总数为 6,最后一个显示的元素是 3,那么容器就展示 2 个元素,最后一项显示 6-3+1 ,即显示 +4。
流程
壳子搭建

页面首次加载时,由于无法确定哪个元素是最后一个显示的,因此先显示所有数据。声明变量数组存储展示数据和全部数据,循环生成高度不固定的元素。最外层容器高度使用随机数生成,模拟不固定高度需求。
js
const height = Math.floor(Math.random() * 400 + 50) + 'px'
const itemArr = reactive([]) // 最终在容器内展示的数据
const itemAll = reactive([]) // 全部的数据
for (let i = 0; i < 20; i++) {
let item = {
test: 'item' + i,
height: Math.floor(Math.random() * 30 + 30) + 'px',
}
itemAll.push(item)
itemArr.push(item)
}vue
<template>
<div
id="father"
class="father"
:style="{
width: '600px'
height: height + 'px'
}"
>
<div id="div1">
<div
v-for="item in itemArr"
class="item"
:style="{
height: item.height,
}"
>
{{ item.text }}
</div>
</div>
</div>
<div>总览: {{ itemAll.height }}</div>
</template>css
.father {
border: 1px solid red;
overflow: hidden;
}
.item {
border: 1px solid blue;
margin-bottom: 10px;
text-align: center;
color: #fff;
}判断最后一个元素
找到最后一个显示在容器内的 DOM 元素,关键 API 是 IntersectionObserver。它是构造函数,接受两个参数:回调函数和配置对象。
该 API 可监听一个或多个元素,获取元素可见性等属性。可见性改变时会再次触发,并拿到改变的元素。
在 onMounted 生命周期钩子中调用该 API,需要两个参数:回调函数会收到所有被观察元素的信息;
获取所有元素,循环为它们绑定 IntersectionObserver,通过 isIntersecting 属性判断当前元素是否可见;通过 intersectionRate 属性获取可见比例,比例为 1 表示完全可见,0.5 表示一半内容可见。
将溢出部分和最后一项从数组截断,计算不显示内容的数量,最后渲染。
js
const initObserver = () => {
let lastIndex = 0 // 最后一个显示的元素索引
const observer = new IntersectionObserver((entries) => {
console.log(entries) // 拿到所有观测的元素信息
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
lastIndex = index
}
})
// 最后一个元素是否百分百显示
if (entries[lastIndex]?.intersectionRate === 1) {
lastIndex -= 1
}
// 判断是否溢出
if (lastIndex < itemArr.length - 1) {
// 可显示的内容
const _arr = itemAll.slice(0, lastIndex)
// 计算不显示的内容的数量
const n = itemAll.length - lastIndex
_arr.push({
text: '+' + n,
height: '40px',
})
itemArr = reactive(_arr)
}
})
const itemList = document.querySelectorAll('.item')
// 这里不能用 forEach,因为 document.querySelectorAll 拿到的是类数组,没有 forEach 方法
for (let i = 0; i < itemList.length; i++) {
// 观察列表每一项
observer.observe(itemList[i])
}
}
onMounted(() => {
initObserver()
})
export default initObserver添加新元素
新增元素后需重新调用 initObserver 方法重新计算,否则不会自动重新计算。
js
import initObserver from ' observer.js'
const addOne = () => {
const addItem = {
text: 'new item',
height: Math.floor(Math.random() * 30 + 30) + 'px',
}
itemAll.unshift(addItem)
itemArr.unshift(addItem)
initObserver()
}