| <template> | 
|   <view class="tn-waterfall-class tn-waterfall"> | 
|     <view id="tn-waterfall-left" class="tn-waterfall__column"><slot name="left" :leftList="leftList"></slot></view> | 
|     <view id="tn-waterfall-right" class="tn-waterfall__column"><slot name="right" :rightList="rightList"></slot></view> | 
|   </view> | 
| </template> | 
|   | 
| <script> | 
|   export default { | 
|     name: 'tn-waterfall', | 
|     props: { | 
|       // 瀑布流数据 | 
|       value: { | 
|         type: Array, | 
|         default() { | 
|           return [] | 
|         } | 
|       }, | 
|       // 数据的id值,根据id值对数据执行删除操作 | 
|       // 如数据为:{id: 1, name: 'tuniao'},那么该值设置为id | 
|       idKey: { | 
|         type: String, | 
|         default: 'id' | 
|       }, | 
|       // 每次插入数据的事件间隔,间隔越长能保证两列高度相近,但是用户体验不好 | 
|       // 单位ms | 
|       addTime: { | 
|         type: Number, | 
|         default: 200 | 
|       } | 
|     }, | 
|     computed: { | 
|       // 破坏value变量引用,否则数据会保持不变 | 
|       copyValue() { | 
|         return this.cloneData(this.value) | 
|       } | 
|     }, | 
|     watch: { | 
|       copyValue(nVal, oVal) { | 
|         // 取出数组发生变化的部分 | 
|         let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0 | 
|         // 拼接原有数据 | 
|         this.tempList = this.tempList.concat(this.cloneData(nVal.slice(startIndex))) | 
|         this.splitData() | 
|       } | 
|     }, | 
|     data() { | 
|       return { | 
|         // 左列表 | 
|         leftList: [], | 
|         // 右列表 | 
|         rightList: [], | 
|         // 临时列表 | 
|         tempList: [] | 
|       } | 
|     }, | 
|     mounted() { | 
|       this.tempList = this.cloneData(this.copyValue) | 
|       this.splitData() | 
|     }, | 
|     methods: { | 
|       // 拆分数据 | 
|       async splitData() { | 
|         if (!this.tempList.length) return | 
|          | 
|         let leftRect = await this._tGetRect('#tn-waterfall-left') | 
|         let rightRect = await this._tGetRect('#tn-waterfall-right') | 
|          | 
|         let item = this.tempList[0] | 
|         // 因为经过上面两个await节点查询和定时器,数组有可能会变成空[],导致item的值为undefined | 
|         // 解决多次快速滚动会导致数据乱的问题 | 
|         if (!item) return | 
|          | 
|         // 如果左边小于或者等于右边,就添加到左边,否则添加到右边 | 
|         if (leftRect.height < rightRect.height) { | 
|           this.leftList.push(item) | 
|         } else if (leftRect.height > rightRect.height) { | 
|           this.rightList.push(item) | 
|         } else { | 
|           // 为了保证前两项添加时,左右两边都还没有内容,这时候根据队列长度判断下一项该放在哪一边 | 
|           if (this.leftList.length <= this.rightList.length) { | 
|             this.leftList.push(item) | 
|           } else { | 
|             this.rightList.push(item) | 
|           } | 
|         } | 
|          | 
|         // 移除临时数组中已处理的数据 | 
|         this.tempList.splice(0, 1) | 
|         // 如果还有数据则继续执行 | 
|         if (this.tempList.length) { | 
|           setTimeout(() => { | 
|             this.splitData() | 
|           }, this.addTime) | 
|         } else { | 
|           this.$emit('finish') | 
|         } | 
|       }, | 
|       // 复制对象和数组(深度复制不会影响原对象和数组) | 
|       cloneData(data) { | 
|         return JSON.parse(JSON.stringify(data)) | 
|       }, | 
|       // 清空数据列表 | 
|       clear() { | 
|         this.leftList = [] | 
|         this.rightList = [] | 
|         this.$emit('input', []) | 
|         this.tempList = [] | 
|       }, | 
|       // 清除指定的某一条数据,根据id来实现 | 
|       remove(id) { | 
|         // 如果查找不到就返回-1 | 
|         let index = -1 | 
|         index = this.leftList.findIndex(val => val[this.idKey] == id) | 
|         if (index != -1) { | 
|           // 如果index不等于-1,说明已经找到了指定的数据 | 
|           this.leftList.splice(index, 1) | 
|         } else { | 
|           // 同理于上面的方法 | 
|           index = this.rightList.findIndex(val => val[this.idKey] == id) | 
|           if (index != -1) this.rightList.splice(index, 1) | 
|         } | 
|         // 同时删除父组件对应的数据 | 
|         index = this.value.findIndex(val => val[this.idKey] == id) | 
|         if (index != -1) this.$emit('input', this.value.splice(index, 1)) | 
|       }, | 
|       // 修改指定数据的属性 | 
|       modify(id, key, value) { | 
|         // 如果查找不到就返回-1 | 
|         let index = -1 | 
|         index = this.leftList.findIndex(val => val[this.idKey] == id) | 
|         if (index != -1) { | 
|           // 如果index不等于-1,说明已经找到了指定的数据 | 
|           this.leftList[index][key] = value | 
|         } else { | 
|           // 同理于上面的方法 | 
|           index = this.rightList.findIndex(val => val[this.idKey] == id) | 
|           if (index != -1) this.rightList[index][key] = value | 
|         } | 
|         // 同时删除父组件对应的数据 | 
|         index = this.value.findIndex(val => val[this.idKey] == id) | 
|         if(index != -1) { | 
|           let data = this.cloneData(this.value) | 
|           data[index][key] = value | 
|           this.$emit('input', data) | 
|         } | 
|       } | 
|     } | 
|   } | 
| </script> | 
|   | 
| <style lang="scss" scoped> | 
|   .tn-waterfall { | 
|     display: flex; | 
|     flex-direction: row; | 
|     align-items: flex-start; | 
|      | 
|     &__column { | 
|       display: flex; | 
|       flex-direction: column; | 
|       flex: 1; | 
|       height: auto; | 
|     } | 
|   } | 
| </style> |