微信小程序实战,基于vue2实现瀑布流

简介: 瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

1、什么是瀑布流呢?

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

瀑布流对于图片的展现,是高效而具有吸引力的,用户一眼扫过的快速阅读模式可以在短时间内获得更多的信息量,而瀑布流里懒加载模式又避免了用户鼠标点击的翻页操作,瀑布流的主要特性便是错落有致,定宽而不定高的设计让页面区别于传统的矩阵式图片布局模式,巧妙的利用视觉层级,视线的任意流动又缓解了视觉疲劳,同时给人以不拘一格的感觉,切中年轻一族的个性化心理。

下面这些就是用瀑布流来实现,看起来是不是很美观呢?
在这里插入图片描述

在这里插入图片描述

2、实现一个简单的瀑布流

先看一下咱们最终的试下效果吧,只是简单传入文字进行演示
在这里插入图片描述

1、瀑布流的特点

1、琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列。

2、唯美:图片的风格以唯美的图片为主。

3、操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前

2、核心算法

通过图片我们可以直观的看到,每一个卡片的高度都是不一样的,需要我们实时能计算高度,同时左右的高度还是不能相互影响。

这里我们主要通过两个数组进行实现,即分为左右数组,核心代码如下:

<view id="u-left-column" class="u-column">
    <slot name="left" :leftList="leftList"></slot>
</view>
<view id="u-right-column" class="u-column">
    <slot name="right" :rightList="rightList"></slot>
</view>

data() {
    return {
        leftList: [],
        rightList: [],
        tempList: [],
        scrollTop: 0,
    }
}

对传入数组进行分组和计算高度

async splitData() {
    if (!this.tempList.length) return;
    let leftRect = await this.$uGetRect('#u-left-column');
    let rightRect = await this.$uGetRect('#u-right-column');
    // 如果左边小于或等于右边,就添加到左边,否则添加到右边
    let item = this.tempList[0];
    // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
    // 数组可能变成[],导致此item值可能为undefined
    if (!item) return;
    if (leftRect.height < rightRect.height) {
        this.leftList.push(item);
    } else if (leftRect.height > rightRect.height) {
        this.rightList.push(item);
    } else {
        // 这里是为了保证第一和第二张添加时,左右都能有内容
        // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
        if (this.leftList.length <= this.rightList.length) {
            this.leftList.push(item);
        } else {
            this.rightList.push(item);
        }
    }
    // 移除临时列表的第一项
    this.tempList.splice(0, 1);
    // 如果临时数组还有数据,继续循环
    if (this.tempList.length) {
        this.splitData();
        return
    }
}

3、完整的组件代码如下

<template>
    <scroll-view class="scroll-y" scroll-y="true" @scrolltolower="tolower" :scroll-top="scrollTop">
        <view class="u-waterfall" id="list">
            <view id="u-left-column" class="u-column">
                <slot name="left" :leftList="leftList"></slot>
            </view>
            <view id="u-right-column" class="u-column">
                <slot name="right" :rightList="rightList"></slot>
            </view>
        </view>
    </scroll-view>
</template>

<script>
    export default {
        name: "waterfall",
        props: {
            value: {
                // 瀑布流数据
                type: Array,
                required: true,
                default: function() {
                    return [];
                }
            },
            scrolltolower: {
                type: Function,
                default: () => {}
            }
        },
        data() {
            return {
                leftList: [],
                rightList: [],
                tempList: [],
                scrollTop: 0,
            }
        },
        watch: {
            copyFlowList(nVal, oVal) {
                this.tempList = this.cloneData(this.copyFlowList);
                this.splitData();
            }
        },
        mounted() {
            this.tempList = this.cloneData(this.copyFlowList);
            this.splitData();
            // this.$on('clearWaterFall', this.clear)
        },
        computed: {
            // 破坏flowList变量的引用,否则watch的结果新旧值是一样的
            copyFlowList() {
                return this.cloneData(this.value);
            }
        },
        methods: {
            async splitData() {
                if (!this.tempList.length) return;
                let leftRect = await this.$uGetRect('#u-left-column');
                let rightRect = await this.$uGetRect('#u-right-column');
                // 如果左边小于或等于右边,就添加到左边,否则添加到右边
                let item = this.tempList[0];
                // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
                // 数组可能变成[],导致此item值可能为undefined
                if (!item) return;
                if (leftRect.height < rightRect.height) {
                    this.leftList.push(item);
                } else if (leftRect.height > rightRect.height) {
                    this.rightList.push(item);
                } else {
                    // 这里是为了保证第一和第二张添加时,左右都能有内容
                    // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
                    if (this.leftList.length <= this.rightList.length) {
                        this.leftList.push(item);
                    } else {
                        this.rightList.push(item);
                    }
                }
                // 移除临时列表的第一项
                this.tempList.splice(0, 1);
                // 如果临时数组还有数据,继续循环
                if (this.tempList.length) {
                    this.splitData();
                    return
                }
            },
            // 复制而不是引用对象和数组
            cloneData(data) {
                return JSON.parse(JSON.stringify(data));
            },
            tolower(e) {
                this.scrolltolower()
            },
            clear() {
                this.leftList = []
                this.rightList = []
            }
        }
    }
</script>

<style lang="scss" scoped>
    @mixin vue-flex($direction: row) {
        /* #ifndef APP-NVUE */
        display: flex;
        flex-direction: $direction;
        /* #endif */
    }

    .scroll-y {
        height: 78vh;
        margin-top: 18px;
    }

    .u-waterfall {
        @include vue-flex;
        flex-direction: row;
        align-items: flex-start;
    }

    .u-column {
        @include vue-flex;
        flex: 1;
        flex-direction: column;
        height: auto;
        width: 45vw;
        word-break: break-all;
    }
</style>

3、简单使用

基于vue的语法进行使用,先进行导入和注册

<script>
import waterfall from '../../component/waterfall/index.vue'
export default {
    name: 'content',
    components: {
        waterfall
    }
}
</script>

因为组件是基于插槽的形式进行开发的,所以我们可以直接传入咱们的样式和标签

<template>
    <view class="main">
        <waterfall :value="dataList" :scrolltolower="getRecommendLove" ref="child">
            <template v-slot:left="left">
                <view v-for="item in left.leftList" :key="item.id" class="left-content" @click="copy(item)">
                    <view class="item">
                        {{item.content}}
                    </view>
                </view>
            </template>
            <template v-slot:right="right">
                <view v-for="item in right.rightList" :key="item.id" class="right-content" @click="copy(item)">
                    <view class="item">
                        {{item.content}}
                    </view>
                </view>
            </template>
        </waterfall>
    </view>
</template>

最终的效果就可以达到我们的目标了

在这里插入图片描述

目录
相关文章
|
16天前
|
人工智能 搜索推荐 安全
从零到一:微信机器人开发的实战心得
从零到一:微信机器人开发的实战心得
51 2
|
1月前
|
小程序 安全 搜索推荐
【微信小程序开发实战项目】——个人中心页面的制作
本文介绍了如何设计和实现一个网上花店的微信小程序,包括个人中心、我的订单和我的地址等功能模块。个人中心让用户能够查看订单历史、管理地址和与客服互动。代码示例展示了`own.wxml`、`own.wxss`和`own.js`文件,用于构建个人中心界面,包括用户信息、订单链接、收藏、地址、客服和版本信息。我的订单部分展示了订单详情,包括商品图片、名称、销量、价格和订单状态,用户可以查看和管理订单。我的地址功能允许用户输入和编辑收货信息,包括联系人、性别、电话、城市和详细地址。每个功能模块都附有相应的WXML和WXSS代码,以及简洁的样式设计。
71 0
【微信小程序开发实战项目】——个人中心页面的制作
|
1月前
|
小程序 开发者
uniapp实战 —— 开发微信小程序的调试技巧
uniapp实战 —— 开发微信小程序的调试技巧
70 1
|
1月前
|
前端开发 小程序
【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)
【微信小程序-原生开发】实用教程20 - 生成海报(实战范例为生成活动海报,内含生成指定页面的小程序二维码,保存图片到手机,canvas 系列教程)
120 0
|
1月前
|
小程序
【微信小程序】实战案例 -- 向订阅用户发送消息(范例:报名提醒)
【微信小程序】实战案例 -- 向订阅用户发送消息(范例:报名提醒)
80 0
|
1月前
|
小程序 前端开发
【微信小程序-原生开发】TDesign 实战模板——聊天气泡
【微信小程序-原生开发】TDesign 实战模板——聊天气泡
23 0
|
1月前
|
小程序
【微信小程序-原生开发】TDesign 实战模板——带性别图标的头像
【微信小程序-原生开发】TDesign 实战模板——带性别图标的头像
35 0
|
1月前
|
小程序 定位技术
【微信小程序-原生开发】TDesign 实战模板——个人信息编辑页
【微信小程序-原生开发】TDesign 实战模板——个人信息编辑页
24 0
|
2天前
|
小程序 前端开发 API
微信小程序全栈开发中的异常处理与日志记录是一个重要而复杂的问题。
微信小程序作为业务拓展的新渠道,其全栈开发涉及前端与后端的紧密配合。本文聚焦小程序开发中的异常处理与日志记录,从前端的网络、页面跳转等异常,到后端的数据库、API调用等问题,详述了如何利用try-catch及日志框架进行有效管理。同时强调了集中式日志管理的重要性,并提醒开发者注意安全性、性能及团队协作等方面,以构建稳定可靠的小程序应用。
8 1
|
2天前
|
小程序 前端开发 API
微信小程序全栈开发中的多端适配与响应式布局是一种高效的开发模式。
探讨小程序全栈开发中的多端适配与响应式布局,旨在实现统一的用户体验。多端适配包括平台和设备适配,确保小程序能在不同环境稳定运行。响应式布局利用媒体查询和弹性布局技术,使界面适应各种屏幕尺寸。实践中需考虑兼容性、性能优化及用户体验,借助跨平台框架如Taro或uni-app可简化开发流程,提升效率。
7 1

热门文章

最新文章