| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <template>
- <view>
- <view class="waterfall-box h-flex-x h-flex-2">
- <view>
- <view v-for="(item,index) in leftList" :key="item._render_id" class="list-item show">
- <helang-waterfall-item :datas="datas" :params="item" tag="left" :index="index" @height="onHeight"
- @click="onClick">
- </helang-waterfall-item>
- </view>
- </view>
- <view>
- <view v-for="(item,index) in rightList" :key="item._render_id" class="list-item show">
- <helang-waterfall-item :datas="datas" :params="item" @height="onHeight" @click="onClick" tag="right"
- :index="index"></helang-waterfall-item>
- </view>
- </view>
- </view>
- <view class="load-txt" v-if="statusText">{{statusText}}</view>
- </view>
- </template>
- <script>
- import helangWaterfallItem from "./waterfall-item.vue"
- export default {
- components: {
- "helang-waterfall-item": helangWaterfallItem
- },
- props: {
- // 组件状态
- status: {
- type: String,
- default: ''
- },
- // 只显示一行
- showlineText: {
- type: String,
- default: ''
- },
- // 等待加载文案
- awaitText: {
- type: String,
- default: '上拉加载更多'
- },
- // 加载中文案
- loadingText: {
- type: String,
- default: '加载中'
- },
- // 加载成功文案,一般与加载中保持一致即可,主要为提示组件可以开始渲染了
- successText: {
- type: String,
- default: '加载中'
- },
- // 加载结束文案,用于没有更多数据时候展示
- finishText: {
- type: String,
- default: '没有更多了'
- },
- // 加载失败文案,用于数据获取异常时展示
- failText: {
- type: String,
- default: '加载失败'
- },
- // 待渲染的数据
- list: {
- type: Array,
- default () {
- return [];
- }
- },
- // 重置列表,设置为 true 时,瀑布流会自动重新渲染列表
- reset: {
- type: Boolean,
- default: false
- },
- datas: {
- type: Object,
- default: ''
- }
- },
- watch: {
- "$props.status"(newValue, oldValue) {
- // 状态变更为 加载成功 时,执行瀑布流数据渲染
- if (newValue == 'success' || newValue == 'await' || newValue == 'showline') {
- if (!this.$props.list || this.$props.list.length < 1) {
- console.log('河浪瀑布流插件提示:当前数据无效');
- return;
- }
- // 若本次渲染为 重置 则先恢复组件的默认参数
- if (this.$props.reset) {
- this.leftHeight = 0;
- this.rightHeight = 0;
- this.leftList = [];
- this.rightList = [];
- this.awaitRenderList = [];
- // 当前展示页码数据
- this.showPage = 1;
- }
- this.awaitRenderList = [...this.$props.list];
- this.renderList();
- }
- }
- },
- computed: {
- statusText() {
- if (!this.$props.status) {
- return false;
- }
- let key = `${this.$props.status}Text`;
- return this.$props[key] || false;
- }
- },
- data() {
- return {
- // 左侧列表高度
- leftHeight: 0,
- // 右侧列表高度
- rightHeight: 0,
- // 左侧列表数据
- leftList: [],
- // 右侧列表数据
- rightList: [],
- // 待渲染列表
- awaitRenderList: [],
- // 当前展示页码数据
- showPage: 1
- }
- },
- methods: {
- // 监听高度变化
- onHeight(height, tag) {
- /**
- * 这个为实际渲染后 CSS 中 margin-buttom 的值,本示例默认为20rpx
- * 用于解决实际渲染后因为数据条数关系,高度差计算偏差的问题
- * */
- let marginBottom = uni.upx2px(20);
- // console.log(`左高:${this.leftHeight},右高:${this.rightHeight},当前高:${height},插入方向:${tag}`)
- if (tag == 'left') {
- this.leftHeight += (height + marginBottom);
- } else {
- this.rightHeight += (height + marginBottom);
- }
- this.renderList();
- },
- // 组件点击事件
- onClick(index, tag) {
- // 对应的数据
- if (tag == 'left') {
- this.$emit("click", this.leftList[index], index, tag);
- } else {
- this.$emit("click", this.rightList[index], index, tag);
- }
- },
- // 渲染列表,这里实现瀑布流的左右分栏
- renderList() {
- // 待渲染长度为 0 时表示已渲染完成
- if (this.awaitRenderList.length < 1) {
- this.showPage++;
- this.$emit("done");
- // 为防止 js 数值类型最大值溢出,当高度值大于 1亿时重置高度
- if (this.leftHeight > 100000000) {
- if (this.leftHeight > this.rightHeight) {
- this.leftHeight = 2;
- this.rightHeight = 1;
- } else {
- this.leftHeight = 1;
- this.rightHeight = 2;
- }
- }
- return;
- }
- let item = {
- ...this.awaitRenderList.splice(0, 1)[0],
- // 当前数据添加当前页面标识
- _current_page: this.showPage,
- // 当前数据添加一个渲染id,解决 v-for 重复会出现不执行 load 的 BUG
- _render_id: new Date().getTime()
- };
- if (this.leftHeight > this.rightHeight) {
- this.rightList.push(item);
- } else {
- this.leftList.push(item);
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .waterfall-box {
- padding: 20rpx 10rpx;
- box-sizing: border-box;
- >view {
- padding: 0 10rpx;
- }
- .list-item {
- margin-bottom: 0;
- // 设置透明,默认是可视的
- opacity: 0;
- // 默认超出隐藏,不影响加载中的文字显示效果
- overflow: hidden;
- height: 0;
- &.show {
- margin-bottom: 20rpx;
- opacity: 1;
- overflow: auto;
- height: auto;
- }
- }
- }
- .h-flex-x {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- justify-content: flex-start;
- align-items: flex-start;
- align-content: flex-start;
- &.h-flex-2 {
- >view {
- width: 50%;
- }
- }
- }
- .load-txt {
- padding: 0 0 20rpx 0;
- text-align: center;
- color: #999;
- font-size: 24rpx;
- }
- </style>
|