瀑布流列表的下拉刷新和上拉加载实现(上)【缺图】
laizimo opened this issue · 0 comments
前言
前段时间,在投票系统中实现了h5的瀑布流加载,demo地址。整体的demo实现效果上可分成三个部分:瀑布流+下拉刷新+上拉加载。下面就具体来分析一下如何实现的。
正文
首先,瀑布流的实现方式只要有三种:
-
在获取内容时,计算出内容的高度,然后使用定位的方式来形成瀑布流(这种方式目前比较常用,但是需要实时计算,性能不是特别高)。
-
获得页面的宽度,然后根据页面的宽度计算列数,在进行固定列表的插入(我是用的就是这一种)
-
使用css3的列布局,由于兼容性问题需要使用前缀(-moz,-webkit)
由于本人使用的是第二种方式,因此,我就详细分析一下第二种方式。
由于设计图是640px的,且整体分成两列,所以,对于列数这个概念,我们可以设定为2,当然了,如果你是PC端的,并不确定列数,你也可以通过window.innerWidth来获取整体的宽度,然后相对于每列的宽度做一个除法。
分析一下整体的html内容部分,主要分为外层的ul,对应的li,以及li里面的内容。
<ul class="container">
<li class="list">
<div class="list-item item1">
</div>
<div class="list-item">
</div>
</li>
<li class="list">
<div class="list-item">
</div>
<div class="list-item">
</div>
</li>
</ul>
然后设置css的样式时,将ul的布局设置为flex布局。
.container{
display: flex;
list-style: none;
padding: 0;
}
.list{
flex: 1;
margin: 10px;
}
.list-item{
width: 100%;
height: 200px;
margin-top: 20px;
background: red;
}
.item1{
height: 100px;
}
这样大致的效果图如下:
之后,我们来写div块的模板函数,方便之后获取数据的插入tepl()
templ: function(data){
const block = doc.createElement('div');
block.className = 'list-item';
const value = `
<img src="${data.image}" alt="person-image">
<div class="name">${data.name}</div>
<div class="info">
<span class="id">编号: ${data.id}</span>
<span class="vote"><span class="count">${data.vote}</span>票</span>
</div>
<div class="desc">
${data.desc}
</div>
<div class="btn-group">
<button class="btn detail" data-value="${data.id}">候选详情</button>
<button class="btn vote" data-value="${data.id}">为TA投票</button>
</div>`;
block.innerHTML = value;
return block;
}
该函数中,就是创建了一个div块,然后给div块赋上classname,之后就是一些固定数据的插入(如果会使用js模板引擎的话,也可以使用,推荐ejs吧)。
之后写一个函数将获取到的数据插入到列表中(由于,我这里还考虑了列表不确定的情况,所以li也是需要临时生成的,同时还需要一个list_number去记录列表数)。先来看一下这部分的函数:
setHtml: function(data){
const _self = this;
const fragments = _self.setFragements(data);
$('.list-wrapper').each((index, item) => {
$(item).append(fragments[index]);
});
},
initHtml: function(data){ //initial html template
const _self = this;
const fragment = doc.createDocumentFragment();
const fragments = _self.setFragements(data);
fragments.forEach((item, index) => {
const listItem = doc.createElement('li');
listItem.className = 'list-wrapper';
listItem.appendChild(item);
fragment.appendChild(listItem);
});
$('.wrapper').html(fragment);
},
setFragements: function(data){ //generate some fragment
const _self = this;
const count = _self.config['list_number'];
const fragments = _self.getFragments(count);
data.forEach((item, index) => {
const i = index % count;
const block = _self.templ(item);
fragments[i].appendChild(block);
});
return fragments;
},
getFragments: function(num){
const arr = [];
for(let i = 0; i < num; i++){
arr.push(doc.createDocumentFragment());
}
return arr;
}
这里的函数主要分为几个功能:插入到html中(非第一次)、初始化html部分、创建fragment。
主要的思路就是第一次加载的时候创建对应的li数量,然后通过fragment片段的形式插入ul中,之后的加载只要获取li的内容,在它的后面进行添加就可以了。
总结
这部分主要是瀑布流以及模板的加载,之后的一篇将会讲下拉刷新和上拉加载的主要思路与实现。整体demo的源码地址在我的github上(demo地址)