微信小程序无限瀑布流

微信小程序无限瀑布流

注意:方便测试使用 Mock.js 来生成假数据,npm install mockjs --save,具体:https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html

pages\index\index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//index.js
//获取应用实例
const app = getApp();

// 引入 mock.js
const mock = require('mockjs');

Page({
data: {
waterfall: {
// 临时列表数据存储
tmp: [],
// 列表数据
list: [],
// 当前页码
page: 1,
// 是否有下一页
more: true,
// 图片宽度
width: 0,
// 列表每列的高度
len: [0, 0],
// 是否正在追加
append: false,
},
},
/**
* 生命周期回调—监听页面显示
*/
onShow() {
this.handleGetData();
},

/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
// 没有下一页数据则不继续调用获取数据
if (!this.data.waterfall.more) return;
this.handleGetData();
},

/**
* 获取数据
*/
handleGetData() {
const data = mock.mock({
'list|10': [{
'id': '@id()',
'title': '@ctitle(5, 8)',
'desc': '@csentence(10, 40)',
'images': function () {
const value = mock.mock('@integer(1, 35)');
return 'https://cdn.hongfs.cn/tmp/miniprogram-waterfall/waterfall/' + value + '.jpg';
},
}],
})['list'];

this.setData({
// 把返回的数据追加到临时存储
'waterfall.tmp': this.data.waterfall.tmp.concat(data),
// 判断返回条数是否不等于规定条数
'waterfall.more': data.length === 10,
}, () => {
// 调用追加函数
this.handleAppendWaterfallImages();
});
},

/**
* 瀑布流追加
*/
handleAppendWaterfallImages() {
// 临时存储没数据了
if (!this.data.waterfall.tmp.length) {
return;
}

// 列表没有数据说明这是第一次调用
if (!this.data.waterfall.list.length) {
this.setData({
'waterfall.list': [
[this.data.waterfall.tmp.shift()],
[]
],
});
return;
}

// 没有图片宽度,需要检查下第一张图片是否正常
if (!this.data.waterfall.width) {
return;
}

// 正在追加中,避免数据混乱
if (this.data.waterfall.append) {
return;
}

// 设置为追加中
this.setData({
'waterfall.append': true,
});

// 获取列表每列的高度
const len = this.data.waterfall.len;
// 判断要追加到哪一列
const len_index = len[0] > len[1] ? 1 : 0;
const len_key = 'waterfall.list[' + len_index + ']';

this.setData({
[len_key]: this.data.waterfall.list[len_index].concat(this.data.waterfall.tmp.shift()),
});
},

/**
* 瀑布流图片加载事件
*/
handleLoadWaterfallImages(e) {
// 当前图片是哪一列
const index = e.target.dataset.index;
const index_key = 'waterfall.len[' + index + ']';

// 不存在图片宽度说明当前是第一条数据
if (!this.data.waterfall.width) {
// 获取列表项信息
wx.createSelectorQuery().select('.waterfall-item').boundingClientRect(rect => {
this.setData({
// 列表项宽度
'waterfall.width': rect.width,
// 当前列表高度
[index_key]: parseInt(rect.width / e.detail.width * e.detail.height),
}, () => {
// 调用追加函数
this.handleAppendWaterfallImages();
});
}).exec();
} else {
const len = this.data.waterfall.len[index];
this.setData({
[index_key]: len + parseInt(this.data.waterfall.width / e.detail.width * e.detail.height),
}, () => {
// 去除追加中状态
this.setData({
'waterfall.append': false,
});
this.handleAppendWaterfallImages();
});
}
},
});

pages\index\index.wxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--index.wxml-->
<view class="container">
<view wx:if="{{ waterfall.list }}" class="waterfall-box">
<view wx:for="{{ waterfall.list }}" wx:for-index="list_index" wx:for-item="list" wx:key="list_index"
class="waterfall-list">
<view wx:for="{{ list }}" wx:key="id" wx:for-item="item" class="waterfall-item">
<image src="{{ item.images }}" mode="widthFix" lazy-load data-index="{{ list_index }}"
bindload="handleLoadWaterfallImages"></image>
<view class="content">
<view class="title">{{ item.title }}</view>
<view class="desc">{{ item.desc }}</view>
</view>
</view>
</view>
</view>
</view>

pages\index\index.wxss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**index.wxss**/
.waterfall-box {
display: flex;
padding: 10px 5px;
background-color: #eee;
}

.waterfall-list {
width: 50%;
}

.waterfall-list+.waterfall-list {
margin-left: 10px;
}

.waterfall-item {
border-radius: 3px;
overflow: hidden;
background-color: #fff;
}

.waterfall-item+.waterfall-item {
margin-top: 10px;
}

.waterfall-item>image {
width: 100%;
}

.waterfall-item .content {
padding: 10px;
}

.waterfall-item .content .title {
font-size: 14px;
margin-bottom: 5px;
}

.waterfall-item .content .desc {
font-size: 12px;
color: #333;
}

效果

其他

微信小程序 image 是个神奇的标签, src 资源是视频居然会自动加载播放。

往上