经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » 微信小程序 » 查看文章
微信小程序实战,基于vue2实现瀑布流
来源:cnblogs  作者:隐风  时间:2022/12/2 11:02:08  对本文有异议

1、什么是瀑布流呢?

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

瀑布流对于图片的展现,是高效而具有吸引力的,用户一眼扫过的快速阅读模式可以在短时间内获得更多的信息量,而瀑布流里懒加载模式又避免了用户鼠标点击的翻页操作,瀑布流的主要特性便是错落有致,定宽而不定高的设计让页面区别于传统的矩阵式图片布局模式,巧妙的利用视觉层级,视线的任意流动又缓解了视觉疲劳,同时给人以不拘一格的感觉,切中年轻一族的个性化心理。

下面这些就是用瀑布流来实现,看起来是不是很美观呢?
在这里插入图片描述

在这里插入图片描述

2、实现一个简单的瀑布流

先看一下咱们最终的试下效果吧,只是简单传入文字进行演示
在这里插入图片描述

1、瀑布流的特点

1、琳琅满目:整版以图片为主,大小不一的图片按照一定的规律排列。

2、唯美:图片的风格以唯美的图片为主。

3、操作简单:在浏览网站的时候只需要轻轻滑动一下鼠标滚轮,一切的美妙的图片精彩便可呈现在你面前

2、核心算法

通过图片我们可以直观的看到,每一个卡片的高度都是不一样的,需要我们实时能计算高度,同时左右的高度还是不能相互影响。

这里我们主要通过两个数组进行实现,即分为左右数组,核心代码如下:

  1. <view id="u-left-column" class="u-column">
  2. <slot name="left" :leftList="leftList"></slot>
  3. </view>
  4. <view id="u-right-column" class="u-column">
  5. <slot name="right" :rightList="rightList"></slot>
  6. </view>
  7. data() {
  8. return {
  9. leftList: [],
  10. rightList: [],
  11. tempList: [],
  12. scrollTop: 0,
  13. }
  14. }

对传入数组进行分组和计算高度

  1. async splitData() {
  2. if (!this.tempList.length) return;
  3. let leftRect = await this.$uGetRect('#u-left-column');
  4. let rightRect = await this.$uGetRect('#u-right-column');
  5. // 如果左边小于或等于右边,就添加到左边,否则添加到右边
  6. let item = this.tempList[0];
  7. // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
  8. // 数组可能变成[],导致此item值可能为undefined
  9. if (!item) return;
  10. if (leftRect.height < rightRect.height) {
  11. this.leftList.push(item);
  12. } else if (leftRect.height > rightRect.height) {
  13. this.rightList.push(item);
  14. } else {
  15. // 这里是为了保证第一和第二张添加时,左右都能有内容
  16. // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
  17. if (this.leftList.length <= this.rightList.length) {
  18. this.leftList.push(item);
  19. } else {
  20. this.rightList.push(item);
  21. }
  22. }
  23. // 移除临时列表的第一项
  24. this.tempList.splice(0, 1);
  25. // 如果临时数组还有数据,继续循环
  26. if (this.tempList.length) {
  27. this.splitData();
  28. return
  29. }
  30. }

3、完整的组件代码如下

  1. <template>
  2. <scroll-view class="scroll-y" scroll-y="true" @scrolltolower="tolower" :scroll-top="scrollTop">
  3. <view class="u-waterfall" id="list">
  4. <view id="u-left-column" class="u-column">
  5. <slot name="left" :leftList="leftList"></slot>
  6. </view>
  7. <view id="u-right-column" class="u-column">
  8. <slot name="right" :rightList="rightList"></slot>
  9. </view>
  10. </view>
  11. </scroll-view>
  12. </template>
  13. <script>
  14. export default {
  15. name: "waterfall",
  16. props: {
  17. value: {
  18. // 瀑布流数据
  19. type: Array,
  20. required: true,
  21. default: function() {
  22. return [];
  23. }
  24. },
  25. scrolltolower: {
  26. type: Function,
  27. default: () => {}
  28. }
  29. },
  30. data() {
  31. return {
  32. leftList: [],
  33. rightList: [],
  34. tempList: [],
  35. scrollTop: 0,
  36. }
  37. },
  38. watch: {
  39. copyFlowList(nVal, oVal) {
  40. this.tempList = this.cloneData(this.copyFlowList);
  41. this.splitData();
  42. }
  43. },
  44. mounted() {
  45. this.tempList = this.cloneData(this.copyFlowList);
  46. this.splitData();
  47. // this.$on('clearWaterFall', this.clear)
  48. },
  49. computed: {
  50. // 破坏flowList变量的引用,否则watch的结果新旧值是一样的
  51. copyFlowList() {
  52. return this.cloneData(this.value);
  53. }
  54. },
  55. methods: {
  56. async splitData() {
  57. if (!this.tempList.length) return;
  58. let leftRect = await this.$uGetRect('#u-left-column');
  59. let rightRect = await this.$uGetRect('#u-right-column');
  60. // 如果左边小于或等于右边,就添加到左边,否则添加到右边
  61. let item = this.tempList[0];
  62. // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
  63. // 数组可能变成[],导致此item值可能为undefined
  64. if (!item) return;
  65. if (leftRect.height < rightRect.height) {
  66. this.leftList.push(item);
  67. } else if (leftRect.height > rightRect.height) {
  68. this.rightList.push(item);
  69. } else {
  70. // 这里是为了保证第一和第二张添加时,左右都能有内容
  71. // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
  72. if (this.leftList.length <= this.rightList.length) {
  73. this.leftList.push(item);
  74. } else {
  75. this.rightList.push(item);
  76. }
  77. }
  78. // 移除临时列表的第一项
  79. this.tempList.splice(0, 1);
  80. // 如果临时数组还有数据,继续循环
  81. if (this.tempList.length) {
  82. this.splitData();
  83. return
  84. }
  85. },
  86. // 复制而不是引用对象和数组
  87. cloneData(data) {
  88. return JSON.parse(JSON.stringify(data));
  89. },
  90. tolower(e) {
  91. this.scrolltolower()
  92. },
  93. clear() {
  94. this.leftList = []
  95. this.rightList = []
  96. }
  97. }
  98. }
  99. </script>
  100. <style lang="scss" scoped>
  101. @mixin vue-flex($direction: row) {
  102. /* #ifndef APP-NVUE */
  103. display: flex;
  104. flex-direction: $direction;
  105. /* #endif */
  106. }
  107. .scroll-y {
  108. height: 78vh;
  109. margin-top: 18px;
  110. }
  111. .u-waterfall {
  112. @include vue-flex;
  113. flex-direction: row;
  114. align-items: flex-start;
  115. }
  116. .u-column {
  117. @include vue-flex;
  118. flex: 1;
  119. flex-direction: column;
  120. height: auto;
  121. width: 45vw;
  122. word-break: break-all;
  123. }
  124. </style>

3、简单使用

基于vue的语法进行使用,先进行导入和注册

  1. <script>
  2. import waterfall from '../../component/waterfall/index.vue'
  3. export default {
  4. name: 'content',
  5. components: {
  6. waterfall
  7. }
  8. }
  9. </script>

因为组件是基于插槽的形式进行开发的,所以我们可以直接传入咱们的样式和标签

  1. <template>
  2. <view class="main">
  3. <waterfall :value="dataList" :scrolltolower="getRecommendLove" ref="child">
  4. <template v-slot:left="left">
  5. <view v-for="item in left.leftList" :key="item.id" class="left-content" @click="copy(item)">
  6. <view class="item">
  7. {{item.content}}
  8. </view>
  9. </view>
  10. </template>
  11. <template v-slot:right="right">
  12. <view v-for="item in right.rightList" :key="item.id" class="right-content" @click="copy(item)">
  13. <view class="item">
  14. {{item.content}}
  15. </view>
  16. </view>
  17. </template>
  18. </waterfall>
  19. </view>
  20. </template>

最终的效果就可以达到我们的目标了

在这里插入图片描述

原文链接:https://www.cnblogs.com/yin-feng/p/16943018.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号