Skip to content

两列瀑布流设计

说一下微信小程序两列瀑布流设计?怎么做

在微信小程序中实现两列瀑布流设计,你可以按照以下步骤来实现:

1. 基本思路

  • 瀑布流布局主要用于展示不规则高度的内容块,并尽量让两列的高度保持平衡。
  • 你可以将每一列视为一个单独的容器,当添加新内容块时,根据两列的当前高度,选择将内容块添加到较矮的那一列。

2. 布局结构

你可以使用 flex 布局或 grid 布局来创建两列的容器:

html
<view class="waterfall-container">
  <view class="column left-column">
    <!-- 左列内容 -->
  </view>
  <view class="column right-column">
    <!-- 右列内容 -->
  </view>
</view>

CSS 样式:

css
.waterfall-container {
  display: flex;
  justify-content: space-between;
}

.column {
  width: 48%;
}

3. 动态插入内容

在小程序中,你可以通过 wx:for 循环遍历数据,将数据项插入到合适的列中:

html
<view class="waterfall-container">
  <view class="column left-column">
    <block wx:for="{{leftColumnData}}" wx:key="index">
      <view class="item">{{item.content}}</view>
    </block>
  </view>
  <view class="column right-column">
    <block wx:for="{{rightColumnData}}" wx:key="index">
      <view class="item">{{item.content}}</view>
    </block>
  </view>
</view>

4. 数据处理逻辑

在数据获取或初始化时,根据每个数据块的高度动态分配到 leftColumnDatarightColumnData 中:

javascript
Page({
  data: {
    leftColumnData: [],
    rightColumnData: [],
  },
  onLoad() {
    const data = this.getData(); // 假设getData返回你的数据列表
    this.splitData(data);
  },
  splitData(data) {
    let leftHeight = 0;
    let rightHeight = 0;
    let leftColumnData = [];
    let rightColumnData = [];

    data.forEach((item) => {
      if (leftHeight <= rightHeight) {
        leftColumnData.push(item);
        leftHeight += item.height; // 假设每个item包含height信息
      } else {
        rightColumnData.push(item);
        rightHeight += item.height;
      }
    });

    this.setData({
      leftColumnData,
      rightColumnData,
    });
  },
});

5. 注意事项

  • 由于 wx:for 不能动态插入元素到特定位置,你可能需要提前计算好数据,分配到两个不同的数组中。
  • 你可以通过图片加载完成后的回调函数来更新每个内容块的高度,从而更精确地分配数据。

这种方式可以让两列尽量保持平衡,并在微信小程序中实现简单的瀑布流布局。根据需要,你还可以进一步优化代码,比如使用懒加载等手段提高性能。

如何加载更多

在微信小程序的两列瀑布流布局中实现加载更多功能,你可以按照以下步骤来完成:

1. 设置触发加载更多的条件

  • 通常,加载更多可以在用户滑动到底部时触发。你可以使用微信小程序的 onReachBottom 事件来监听用户滑动到底部的动作。

page 中定义 onReachBottom 方法:

javascript
Page({
  data: {
    leftColumnData: [],
    rightColumnData: [],
    page: 1, // 当前加载的页数
    pageSize: 10, // 每次加载的条数
    isLoading: false, // 是否正在加载
  },
  onLoad() {
    this.loadMoreData();
  },
  onReachBottom() {
    this.loadMoreData();
  },
  loadMoreData() {
    if (this.data.isLoading) return;

    this.setData({ isLoading: true });

    const newPage = this.data.page + 1;
    // 模拟请求数据
    wx.request({
      url: "your-api-url",
      data: {
        page: newPage,
        pageSize: this.data.pageSize,
      },
      success: (res) => {
        const newData = res.data; // 假设返回的数据列表
        this.splitData(newData);
        this.setData({
          page: newPage,
          isLoading: false,
        });
      },
      fail: () => {
        this.setData({ isLoading: false });
      },
    });
  },
  splitData(data) {
    let leftHeight = 0;
    let rightHeight = 0;
    const leftColumnData = this.data.leftColumnData;
    const rightColumnData = this.data.rightColumnData;

    data.forEach((item) => {
      if (leftHeight <= rightHeight) {
        leftColumnData.push(item);
        leftHeight += item.height; // 假设每个item包含height信息
      } else {
        rightColumnData.push(item);
        rightHeight += item.height;
      }
    });

    this.setData({
      leftColumnData,
      rightColumnData,
    });
  },
});

2. 分页加载

  • loadMoreData 方法中,每次请求新的数据时,需要传递当前页码 page 和每页数据条数 pageSize。并在获取数据后,将新数据合并到已有的 leftColumnDatarightColumnData 中。

3. 显示加载中状态

  • 在页面底部,可以显示一个加载中的提示,告知用户正在加载更多内容。可以在 wxml 文件中添加一个 loading 提示:
html
<view wx:if="{{isLoading}}" class="loading"> 加载中... </view>

对应的样式:

css
.loading {
  text-align: center;
  padding: 10px;
}

4. 处理无更多数据的情况

  • 如果后台返回的数据长度小于 pageSize,说明可能已经没有更多数据,这时可以停止触发加载更多。
javascript
loadMoreData() {
  if (this.data.isLoading) return;

  this.setData({ isLoading: true });

  const newPage = this.data.page + 1;
  wx.request({
    url: 'your-api-url',
    data: {
      page: newPage,
      pageSize: this.data.pageSize
    },
    success: (res) => {
      const newData = res.data;

      if (newData.length < this.data.pageSize) {
        this.setData({ isLoading: false, hasMore: false });
      } else {
        this.splitData(newData);
        this.setData({
          page: newPage,
          isLoading: false
        });
      }
    },
    fail: () => {
      this.setData({ isLoading: false });
    }
  });
}

5. 优化用户体验

  • 你可以使用 wx.showLoadingwx.hideLoading 来提示用户加载状态。
  • 如果数据加载失败,可以提示用户,并提供重试的选项。

这样,用户在滑动页面到底部时会自动加载更多内容,并在数据加载完成后动态更新瀑布流布局。

如何性能优化

在微信小程序中实现两列瀑布流布局并加载更多内容时,进行性能优化非常重要,特别是在数据量较大或图片较多的情况下。以下是一些性能优化的建议:

1. 懒加载图片

  • 使用小程序的 lazy-load 属性,确保图片只有在用户即将看到时才加载,减少首屏加载时间和数据传输量。
html
<image src="{{item.src}}" lazy-load="{{true}}" class="item-image"></image>

2. 合并请求,减少请求次数

  • 每次加载更多数据时,尽量请求更多的数据以减少请求次数。可以调整 pageSize 的值,适当增加每次加载的数据量。
  • 通过后端合并请求返回的数据,避免前端多次发起请求。

3. 数据去重与增量加载

  • 每次加载新数据时,确保新数据不会与现有数据重复。这可以通过唯一 ID 或其他标识符来判断,避免重复渲染。

4. 减少 DOM 操作

  • 在更新数据时,尽量减少不必要的 DOM 操作。比如,如果已经确定数据是追加的,就不要重复渲染整个列表,而只渲染新增部分。

5. 使用 virtual-listrecycler-view(如果适用)

  • 虽然微信小程序没有原生的 virtual-list 支持,但你可以借助社区的虚拟列表组件或自己实现简单的虚拟列表。虚拟列表通过只渲染可见区域的数据项,极大地提高了长列表的渲染性能。

6. 优化图片加载与处理

  • 使用 CDN 加速图片加载,确保图片资源的访问速度。
  • 对图片进行压缩,减少图片的文件大小,同时可以在合适的场景下使用 WebP 格式的图片。

7. 防抖与节流

  • 对于频繁触发的事件(如滚动、窗口调整),使用防抖或节流技术减少计算和 DOM 更新频率。
javascript
function throttle(fn, delay) {
  let lastTime = 0;
  return function (...args) {
    const now = new Date().getTime();
    if (now - lastTime >= delay) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

在滚动事件中使用:

javascript
onPageScroll: throttle(function (e) {
  // 滚动相关逻辑
}, 200);

8. 优先展示首屏内容

  • 在数据量较大时,优先加载和渲染首屏数据,其余数据可以通过异步请求或用户滚动触发加载。
  • 这样可以让用户在短时间内看到页面内容,提升页面加载体验。

9. 使用 requestAnimationFrame 优化动画和滚动性能

  • 对于动画效果和滚动操作,使用 requestAnimationFrame 来优化渲染性能,确保动画的流畅性。
javascript
function smoothScroll() {
  requestAnimationFrame(smoothScroll);
  // 你的滚动或动画逻辑
}

10. 分批渲染数据

  • 如果一次性要加载大量数据,考虑将数据分批渲染到页面中。例如,可以通过 setTimeout 将渲染操作分成几部分,避免主线程阻塞。
javascript
function batchRender(data, batchSize = 20) {
  let index = 0;
  function renderBatch() {
    const nextBatch = data.slice(index, index + batchSize);
    // 渲染操作
    index += batchSize;
    if (index < data.length) {
      setTimeout(renderBatch, 0);
    }
  }
  renderBatch();
}

11. 使用 web-worker 进行复杂计算

  • 如果有复杂的计算任务,可以通过微信小程序的 Worker 来异步处理,避免阻塞主线程。

12. 减少 setData 调用

  • 避免频繁调用 setData,特别是大量数据更新时,尽量将数据合并到一次 setData 中进行更新。

13. 缓存数据

  • 对于多次请求相同的数据,可以使用缓存技术(如 wx.setStorageSync)减少网络请求的频率,提升数据获取速度。

通过以上这些方法,你可以大幅度优化微信小程序两列瀑布流的加载和渲染性能,提供更好的用户体验。