info
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<view class="tui-waterfall__box"
|
||||
:style="{ paddingLeft: leftGap, paddingRight: rightGap, background: backgroundColor, borderRadius: radius }">
|
||||
<view class="tui-waterfall__list" id="tui-waterfall__left" :style="{ marginRight: columnGap }">
|
||||
<view v-for="(item, index) in leftList" :key="index">
|
||||
<slot name="left" :entity="item" :index="index" :isList="columnCount==1"></slot>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="columnCount > 1" class="tui-waterfall__list" id="tui-waterfall__right">
|
||||
<view v-for="(item, index) in rightList" :key="index">
|
||||
<slot name="right" :entity="item" :index="index" :isList="columnCount==1"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 列表中图片可以使用懒加载或者其他方式
|
||||
* 优先计算出图片高度,以达到最佳效果
|
||||
* App端建议使用weex的waterfall组件,使用案例详见:
|
||||
* [ThorUI组件库->pages->index->productNvue]
|
||||
*/
|
||||
export default {
|
||||
name: 'tuiWaterfall',
|
||||
props: {
|
||||
//列表数据,不建议一次性加载过多数据
|
||||
listData: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
//每页数据条数(固定条数),当数据长度小于等于该数时表示第一页数据,刷新重置
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
//数据分组类型:1-简单左右分组,按顺序排列,伪瀑布流 2-计算左右容器高度进行分组
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
//瀑布流列数,目前支持最大值为2
|
||||
columnCount: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
//列与列的间隙
|
||||
columnGap: {
|
||||
type: String,
|
||||
default: '10rpx'
|
||||
},
|
||||
//左侧和列表的间隙
|
||||
leftGap: {
|
||||
type: String,
|
||||
default: '0'
|
||||
},
|
||||
//右侧和列表的间隙
|
||||
rightGap: {
|
||||
type: String,
|
||||
default: '0'
|
||||
},
|
||||
//列表背景色,可使用渐变色
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: 'transparent'
|
||||
},
|
||||
//列表外层容器圆角值
|
||||
radius: {
|
||||
type: String,
|
||||
default: '0'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
leftListConst: [],
|
||||
leftList: [],
|
||||
rightList: [],
|
||||
running: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
listData(val) {
|
||||
this.columnChange();
|
||||
},
|
||||
columnCount(val) {
|
||||
this.columnChange(val);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.columnChange();
|
||||
},
|
||||
methods: {
|
||||
columnChange(val) {
|
||||
if (this.columnCount < 2) {
|
||||
this.leftList = [...this.listData];
|
||||
} else {
|
||||
if (val && val == 2) {
|
||||
this.leftList = [...this.leftListConst]
|
||||
}
|
||||
this.initData()
|
||||
}
|
||||
},
|
||||
initData() {
|
||||
if (this.type == 1) {
|
||||
this.getSubGroup();
|
||||
} else {
|
||||
this.getArrayByHeight();
|
||||
}
|
||||
},
|
||||
getDiffList() {
|
||||
let diffList = [];
|
||||
let total = this.listData.length;
|
||||
if (total <= this.pageSize) {
|
||||
console.info('running clean func')
|
||||
this.leftListConst = [];
|
||||
this.leftList = [];
|
||||
this.rightList = [];
|
||||
}
|
||||
let sum = this.leftListConst.length + this.rightList.length;
|
||||
let diff = total - sum;
|
||||
if (diff > 0) {
|
||||
diffList = [...this.listData].filter((item, index) => {
|
||||
return index >= sum;
|
||||
});
|
||||
}
|
||||
return diffList;
|
||||
},
|
||||
getSubGroup() {
|
||||
//type=1时执行简单数据分组
|
||||
if (!this.listData && this.listData.length === 0) return;
|
||||
let leftList = [];
|
||||
let rightList = [];
|
||||
let data = this.getDiffList();
|
||||
data.forEach((item, index) => {
|
||||
if (index % 2 === 0) {
|
||||
leftList.push(item);
|
||||
} else {
|
||||
rightList.push(item);
|
||||
}
|
||||
});
|
||||
this.leftList = this.leftList.concat(leftList);
|
||||
this.leftListConst = this.leftListConst.concat(leftList);
|
||||
this.rightList = this.rightList.concat(rightList);
|
||||
},
|
||||
async getArrayByHeight() {
|
||||
// 如果在计算了,则跳过
|
||||
if (this.running === true) {
|
||||
// 如果重置页面,则不再加载;
|
||||
if (this.listData.length <= this.pageSize) return false;
|
||||
setTimeout(() => {this.getArrayByHeight()}, 100);
|
||||
return false;
|
||||
}
|
||||
this.running = true;
|
||||
if (!this.listData && this.listData.length === 0) return;
|
||||
console.info('getArrayByHeight');
|
||||
let data = this.getDiffList();
|
||||
for (let item of data) {
|
||||
await this.render(item);
|
||||
}
|
||||
this.running = false;
|
||||
},
|
||||
async render(item) {
|
||||
console.info(item.id);
|
||||
let obj = await this.getContainerHeight();
|
||||
return await new Promise((resolve, reject) => {
|
||||
if (obj && typeof obj.leftHeight === 'number') {
|
||||
if (obj.leftHeight <= obj.rightHeight) {
|
||||
this.leftList.push(item);
|
||||
this.leftListConst.push(item);
|
||||
} else {
|
||||
this.rightList.push(item);
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
resolve(true);
|
||||
}, 30);
|
||||
});
|
||||
} else {
|
||||
reject(false);
|
||||
}
|
||||
});
|
||||
},
|
||||
async getContainerHeight() {
|
||||
//type=2
|
||||
return await new Promise((resolve, reject) => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
let nodes = query.selectAll('#tui-waterfall__left, #tui-waterfall__right');
|
||||
nodes.boundingClientRect().exec(res => {
|
||||
if (res && res[0]) {
|
||||
const rects = res[0];
|
||||
const leftHeight = rects[0].height;
|
||||
const rightHeight = rects[1].height;
|
||||
resolve({
|
||||
leftHeight: leftHeight,
|
||||
rightHeight: rightHeight
|
||||
});
|
||||
} else {
|
||||
reject(res);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tui-waterfall__box {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
box-sizing: border-box;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.tui-waterfall__list {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user