类小红书的社交卡片瀑布流

接到一个瀑布流布局的需求,网上找了一遍也没有找到合适的实现方式。无奈之下只能自己实现了。

先看效果:

实现思路

  1. 遍历列表创建异步任务(用任务队列管理),单个任务渲染一个卡片(计算获取最短列,然后将卡片推入最短列中)
  2. 使用 IntersectionObserver 监听加载,当滚动到底部时加载更多数据。

废话不多说,上代码吧

瀑布流渲染逻辑

这里进行了浅对比,如果判断是新增元素的情况,则不需要全部重新渲染,只需要将新增的数据创建对应异步任务即可

scss 复制代码
​
watch(
    [() => props.list],
    ([list], [prevList]) => {
        // 判断是不是新增了元素
        if (Array.isArray(list) && Array.isArray(prevList) && list.length > prevList.length && shallowCompareFirstNElements(list, prevList, prevList.length)) {
            const newArr = list.slice(prevList.length);
            distributeNewItems(newArr);
        } else {
            taskQueue.clear();
            initColumns();
            if (list.length > 0) {
                distributeNewItems(list);
            }
        }
    },
    {
        immediate: true,
    }
)

列高度计算逻辑

ini 复制代码
// 计算列高度
const updateColumnHeights = async () => {
    await nextTick();
    columns.value?.forEach(column => {
        const element = document.getElementById(column.id);
        if (element) {
            const rect = element.getBoundingClientRect();
            column.height = rect.height ?? 0;
        }
    });
};

异步任务创建逻辑

scss 复制代码
// 追加新数据到瀑布流
const distributeNewItems = (newItems: any[]) => {
    newItems.forEach(item => {
        const task = () => new Promise(async (resolve, reject) => {
            try {
                await updateColumnHeights()
                const shortestIndex = findShortestColumnIndex();
                columns.value[shortestIndex].items.push({ data: item, imageLoaded: () => resolve('') });
                if (!props.hasImage) {
                    resolve('');
                }
            } catch (err) {
                console.log(err);
                reject(err);
            }
        });
        taskQueue.enqueue(task);
    });
};

完整的逻辑请看可查看git仓库: github.com/KaiEi1020/w...

demo 还比较粗糙,有什么问题和建议欢迎讨论

相关推荐
前端双越老师6 小时前
程序员 1v1 访谈系列第十期:纯前端坚持不了多久了
前端·ai编程·全栈
ruanno_top7 小时前
Vue 3 后台权限路由:我漏掉了按钮级裁剪,还把 403 写成了 404
vue.js
门思科技7 小时前
LoRaWAN 网络排障的五层漏斗:从"上不到云"到"数值不对",每一层该用什么工具证明
前端
计算机魔术师7 小时前
Cursor 官方插件商城现恶意 Claude Code 扩展,约 11 小时影响最多 5000 名开发者
前端
掘金者阿豪7 小时前
MongoDB迁移到金仓数据库:商品属性继续灵活存,订单报表交给 SQL
前端·后端
栉甜8 小时前
Vue2学习内容(上)
前端·javascript·vue.js·学习
梦曦i8 小时前
v0.2.0 架构升级:class + reactive 重塑状态管理
前端·uni-app x
布丁爱干饭8 小时前
寄给午后
前端
java1234_小锋8 小时前
【技术专题】CSS3 网页技术 - CSS3 布局进阶
前端·css·css3
zhippt_10149 小时前
只剩截图没有源文件?图转PPT把图片还原成可编辑幻灯片
前端·人工智能·powerpoint