tm-flowLayout.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <template>
  2. <view class="tm-flowLayout relative">
  3. <view class="tm-flowLayout-hidden absolute fulled" >
  4. <view v-for="(item, index) in list2" :key="index" style="width: 350rpx;" :class="'tm-flowLayout-hidden-'+index" >
  5. <tm-images @error="loadimg($event,false,index)" @load="loadimg($event,true,index)" :src="item.image"></tm-images>
  6. </view>
  7. </view>
  8. <view class="tm-flowLayout-cm flex-between">
  9. <view class="tm-flowLayout-left" style="width: 48.6%;">
  10. <block v-for="(item, index) in dataList[0]" :key="index">
  11. <view @click.stop="onclick(index,0)" class="tm-flowLayout-item mb-20 fulled" :class="['tm-flowLayout-item_'+index]" >
  12. <slot name="left" :hdata="{item:item,dirIndex:0,childrenIndex:index}">
  13. <tm-images v-if="item.image" :src="item.image"></tm-images>
  14. </slot>
  15. </view>
  16. </block>
  17. </view>
  18. <view class="tm-flowLayout-right" style="width: 48.6%;">
  19. <block v-for="(item, index) in dataList[1]" :key="index">
  20. <view @click.stop="onclick(index,1)" class="tm-flowLayout-item mb-20 fulled" :class="['tm-flowLayout-item_'+index]">
  21. <slot name="right" :hdata="{item:item,dirIndex:1,childrenIndex:index}">
  22. <tm-images v-if="item.image" :src="item.image"></tm-images>
  23. </slot>
  24. </view>
  25. </block>
  26. </view>
  27. </view>
  28. <view v-if="isLoading" class="flex-shrink fulled">
  29. <tm-loadding></tm-loadding>
  30. </view>
  31. </view>
  32. </template>
  33. <script>
  34. /**
  35. * 瀑布流组件
  36. * @property {Function} click 点击项目时触发
  37. * @property {Function} load 当前列表加载完成发出的事件。
  38. * @property {String} model = [rank|desc] desc下正时排序,所有加载完成再进行显示,rank随机,哪个先加载哪个先排前面。
  39. */
  40. import tmImages from "@/tm-vuetify/components/tm-images/tm-images.vue"
  41. import tmLoadding from "@/tm-vuetify/components/tm-loadding/tm-loadding.vue"
  42. import tmIcons from "@/tm-vuetify/components/tm-icons/tm-icons.vue"
  43. export default {
  44. components:{tmImages,tmLoadding,tmIcons},
  45. name: 'tm-flowLayout',
  46. props:{
  47. model:{
  48. type:String,
  49. default:'rank' //desc下正时排序,所有加载完成再进行显示,rank随机,哪个先加载哪个先排前面。
  50. }
  51. },
  52. data() {
  53. return {
  54. list2:[],
  55. dataList:[
  56. [],[]
  57. ],
  58. colHeight:[0,0],
  59. minWidth:0,
  60. isLoading:true,
  61. };
  62. },
  63. async mounted() {
  64. let p = await this.$Querey('.tm-flowLayout-left').catch(e=>{});
  65. this.minWidth = p[0].width;
  66. },
  67. methods: {
  68. onclick(index,dirIndex){
  69. this.$emit('click',
  70. {
  71. childrenIndex:index,
  72. dirIndex:dirIndex,
  73. item:this.dataList[dirIndex][index]
  74. });
  75. },
  76. //修改或者替换列表数据
  77. changeItemData(dirIndex,childrenIndex,item){
  78. this.dataList[dirIndex].splice(childrenIndex,1,item);
  79. },
  80. //删除一项列表数据
  81. delItemData(dirIndex,childrenIndex){
  82. this.colHeight.splice(dirIndex,1,this.colHeight[dirIndex] - this.dataList[dirIndex][childrenIndex].height)
  83. this.dataList[dirIndex].splice(childrenIndex,1);
  84. this.list2.splice(this.dataList[dirIndex][childrenIndex].index,1);
  85. this.$nextTick(function(){
  86. this.sucessRank();
  87. })
  88. },
  89. //向列表添加数据
  90. pushData(list){
  91. let prIdx_i = this.list2.length;
  92. if(!Array.isArray(list)||typeof list =='undefined'){
  93. return false;
  94. }
  95. for(let i=0;i<list.length;i++){
  96. this.list2.push({
  97. index:i+prIdx_i,
  98. isLoad:false,
  99. image:"",
  100. width:0,
  101. height:0,
  102. ...list[i]
  103. })
  104. }
  105. },
  106. //获取内部列表数据
  107. getDataList(){
  108. return this.dataList;
  109. },
  110. async loadimg(event,isLoad,index) {
  111. // console.log(event,index);
  112. this.isLoading = true;
  113. let ps = this.list2[index];
  114. ps.isLoad = true;
  115. if(isLoad==false){
  116. ps.width = this.minWidth;
  117. ps.height = this.minWidth;
  118. }else{
  119. ps.width = this.minWidth;
  120. ps.height = ps.height+event.height;
  121. }
  122. if(this.list2.length==0&&this.dataList[0].length==0&&this.dataList[1].length==0){
  123. this.isLoading = false;
  124. return;
  125. }
  126. this.list2.splice(index,1,ps);
  127. if(this.model=='desc'){
  128. this.sucessRank();
  129. }else if(this.model == 'rank'){
  130. let indexCol = this.colHeight[0]<=this.colHeight[1]?0:1;
  131. this.dataList[indexCol].push(this.list2[index]);
  132. this.colHeight.splice(indexCol,1,this.colHeight[indexCol]+this.list2[index].height);
  133. if(this.isAllLoading()===false) return;
  134. this.isLoading = false;
  135. }
  136. },
  137. isAllLoading(){
  138. let isAllload = true;
  139. for(let i=0;i<this.list2.length;i++){
  140. if(this.list2[i].isLoad===false){
  141. isAllload = false;
  142. break;
  143. }
  144. }
  145. if(isAllload===true){
  146. // 当前列表加载完成发出的事件。
  147. this.$emit('load',this.dataList)
  148. }
  149. return isAllload;
  150. },
  151. sucessRank(){
  152. if(this.isAllLoading()===false) return;
  153. this.isLoading = false;
  154. for(let i=0;i<this.list2.length;i++){
  155. // let p = await this.getLeftRightHeight();
  156. let index = this.colHeight[0]<=this.colHeight[1]?0:1;
  157. this.dataList[index].push(this.list2[i]);
  158. this.colHeight.splice(index,1,this.colHeight[index]+this.list2[i].height)
  159. }
  160. },
  161. //清空瀑布流数据 。
  162. clear(){
  163. this.list2 = [];
  164. this.dataList = [[],[]];
  165. this.isLoading = false;
  166. },
  167. getLeftRightHeight(index){
  168. let t = this;
  169. return new Promise((resolve,rejecvt)=>{
  170. let q = uni.createSelectorQuery().in(t);
  171. q.select(".tm-flowLayout-left").boundingClientRect();
  172. q.select(".tm-flowLayout-right").boundingClientRect();
  173. q.exec((res)=>{
  174. resolve([res[0].height,res[1].height])
  175. })
  176. })
  177. }
  178. },
  179. };
  180. </script>
  181. <style lang="scss">
  182. .tm-flowLayout {
  183. .tm-flowLayout-hidden{
  184. width: 100%;
  185. height: 100px;
  186. overflow-y: auto;
  187. left: -300%;
  188. top: 0;
  189. }
  190. .tm-flowLayout-cm{
  191. align-items: flex-start;
  192. }
  193. }
  194. </style>