Open laizimo opened 6 years ago
前段时间,在投票系统中实现了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地址)
前言
前段时间,在投票系统中实现了h5的瀑布流加载,demo地址。整体的demo实现效果上可分成三个部分:瀑布流+下拉刷新+上拉加载。下面就具体来分析一下如何实现的。
正文
首先,瀑布流的实现方式只要有三种:
在获取内容时,计算出内容的高度,然后使用定位的方式来形成瀑布流(这种方式目前比较常用,但是需要实时计算,性能不是特别高)。
获得页面的宽度,然后根据页面的宽度计算列数,在进行固定列表的插入(我是用的就是这一种)
使用css3的列布局,由于兼容性问题需要使用前缀(-moz,-webkit)
由于本人使用的是第二种方式,因此,我就详细分析一下第二种方式。
由于设计图是640px的,且整体分成两列,所以,对于列数这个概念,我们可以设定为2,当然了,如果你是PC端的,并不确定列数,你也可以通过window.innerWidth来获取整体的宽度,然后相对于每列的宽度做一个除法。
分析一下整体的html内容部分,主要分为外层的ul,对应的li,以及li里面的内容。
然后设置css的样式时,将ul的布局设置为flex布局。
这样大致的效果图如下:
之后,我们来写div块的模板函数,方便之后获取数据的插入tepl()
该函数中,就是创建了一个div块,然后给div块赋上classname,之后就是一些固定数据的插入(如果会使用js模板引擎的话,也可以使用,推荐ejs吧)。
之后写一个函数将获取到的数据插入到列表中(由于,我这里还考虑了列表不确定的情况,所以li也是需要临时生成的,同时还需要一个list_number去记录列表数)。先来看一下这部分的函数:
这里的函数主要分为几个功能:插入到html中(非第一次)、初始化html部分、创建fragment。
主要的思路就是第一次加载的时候创建对应的li数量,然后通过fragment片段的形式插入ul中,之后的加载只要获取li的内容,在它的后面进行添加就可以了。
总结
这部分主要是瀑布流以及模板的加载,之后的一篇将会讲下拉刷新和上拉加载的主要思路与实现。整体demo的源码地址在我的github上(demo地址)