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

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

先看效果:

实现思路

  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***34911 分钟前
Vue混合现实案例
前端·vue.js·mr
p***434818 分钟前
Vue混合现实开发
前端·vue.js·mr
ArkPppp19 分钟前
大道至简-Shadcn/ui设计系统初体验(下):Theme与色彩系统实战
前端·前端框架
炒米233320 分钟前
通义千问Qwen3-Coder模型帮我总结的typescript笔记
前端
__花花世界26 分钟前
前端日常工作开发技巧汇总
前端·javascript·vue.js
0思必得038 分钟前
[Web自动化] HTTP/HTTPS协议
前端·python·http·自动化·网络基础·web自动化
冰封剑心1 小时前
MiniCPM-V-2_6 (4-bit 量化)使用
java·前端·数据库
q***42821 小时前
SpringCloudGateWay
android·前端·后端
爱泡脚的鸡腿1 小时前
uni-app D5 实战(小兔鲜)
前端
tomato_4041 小时前
本地系统、虚拟机、远程服务器三者之间的核心区别
前端