很少写文章,很乱,,见谅。
我所见过的瀑布流都是固定的几列,然后每一列包含若干个元素(图文元素),每一列的总高度都差不多。
所以我这个组件的功能就很简单,可以设置列数量,然后只要再写一个渲染元素的方法,即可使用。
组件说明
组件名:
参数名 | 类型 | 说明 |
---|---|---|
data | Array | 数据源 |
column_size | Number | 列的数量 |
renderItem | Function | 目前只能通过render函数渲染子元素,还不支持模板。 有三个参数 h, item,将被渲染的元素 next,是一个function,在渲染子元素的合适时机(例如img的onload事件里),调用next()即可。 如不调用next将只能渲染一个元素,无法继续渲染。 |
一个简单的使用例子如下:
export default {
data() {
// 随机生成20个测试数据
const num = 20;
var list = new Array(num).fill(0).map((v, i) => {
return this.createItem(i);
})
return {
list,
}
},
// 直接用render函数来写,因为我觉得这样写props更直观一点
render(h){
return h('tag-autoflow', {
props:{
// 设置列数量
column_size:3,
// 数据源
data: this.list,
// 渲染item的方法,参数目前提供三个
// h 瀑布流组件的createElement方法,非父组件的
// item 要渲染的元素对象
// next 必须主动调用next,插件才会自动去渲染下一个元素,详细说明见下文
renderItem(h, item, next){
// 简单的渲染一个img跟一个p标签
// 因为img标签的图片加载需要时间,而图片影响了计算所在列的高度
// 所以需要在img触发了load事件后,再去调用next渲染下一个item。
return h('div', [
h('img', {
attrs: {
src: item.img
},
on: {
load: e => {
next();
}
}
}),
h('p', item.title)
])
},
},
});
},
methods:{
createItem(i) {
var title = i + ',' + new Array(_.random(10, 150)).fill('哈').join('');
var img = `http://via.placeholder.com/${_.random(100, 400)}x${_.random(100, 400)}`;
return {
img,
title,
}
},
}
}
放一张渣渣效果图吧。。。
代码里是一次性生成的20个元素,页面渲染的时候,很明显的能看出来是在一个img触发了load事件之后才渲染下一个元素。
如果花点心思加一些动画效果应该很酷吧。
如果你要渲染的item不包含图片,纯文字的话,可以通过这种写法调用next。保证了计算列高度的准确性。
renderItem(h, item, next){
this.$nextTick(function(){
next();
});
return h('p', item.title);
},
瀑布流的流程说明
先根据参数生成对应数量的列,
判断data是否有元素,没有就结束。
从data里面shift()拿到一个元素item,
找出当前高度最小的一列,将item放入该列。
渲染item,然后调用next()方法进入2
TODO
瀑布流还有个常见的功能就是滚动加载了,目前尚未加入此功能,会尽快加上。
元素加载的过渡动画