前情提要:

  1. 这是个移动端H5项目
  2. 需求是一个类淘宝的两列,每个商品卡的高度在两个选项中随机选择
  3. 商品可能有几百个,所以配置有无限加载和分页
  4. 最终使用方案:flexbox

摘要:

一共三种方案,先列举一下优缺点,再说实现

  • flexbox
    • 优点:
      • flex布局移动端兼容好;
      • 实现简单没有坑;
      • 淘宝瀑布流也用的这个
    • 缺点:
      • 需要手动创建两个dom,如果变成三列就是手动创建三个dom,不好扩展;
      • 两列商品之间布局互不影响,可能高低差非常明显
  • grid
    • 优点:两列商品布局相互影响,看起来很整齐
    • 缺点:
      • 移动端兼容性相对没那么好;
      • 坑!!商品多了之后有大坑!!详见下文
  • multi-column

    • 优点:实现简单,纯css实现
    • 缺点:每次添加数据会引发全局重排

      flexbox

      原理非常简单,见图:
      image.png
      代码版就是:
      点击查看【codepen】
      其中 area-1,area-2 根据两个数组进行渲染,所以数据拿到手之后要平分处理为两个变量。
      这里额外说一点:

    • 为什么在插入数组时我不进行两边的高度差判断,动态的append数据进去,让两边差不多高度?

      • 业务需求对某个商品出现在某个特定位置有需求,并且是个配置项;和产品双方的共识是,配置大于小部分美观,并且这是个无限加载,看到底部的可能性也很小。

        multi-column

        1. .item-list-extra {
        2. column-count: 2;
        3. column-gap: 10px;
        4. }
        5. .item {
        6. break-inside: avoid;
        7. }
        之前看到过一篇两行代码写出瀑布流的,就是用的这个。
        原理很简单,就是使用 column-count 这个css属性,将内容分为2列,这个属性的兼容性也不错,除了IE10以下都兼容。
        但是有两个致命的问题:
  1. 这个属性是把内容区的所有dom按照 左上 -> 左下 -> 右上 -> 右下 的顺序重排,也就是说与我们日常的从左到右,从上到下的顺序完全不符合,类似于下面代码,虽然可以通过对初始数据处理来保证顺序,但是相对不好维护:

点击查看【codepen】

  1. 同样因为第一点,column-count 会时刻监控dom的变化,在加载到新数据时进行重排,一方面性能消耗比较大,一方面体验非常非常奇怪,见真实环境截屏(项目已下线,不牵扯数据泄密),重点关注右边列: 屏幕录制 2020-07-08 下午5.16.31.mov (15.78MB)

    grid

  • grid 其实就是格子布局,事先设定好格子每行的高度是20px,里面的商品元素占12行格子或者13行格子,从而形成参差。

点击查看【codepen】

超级大坑

  • 一个dom容器中能容纳的 grid-row 的行数是有限的,测试出来是999行。当这个dom容器中的行数超过999时,append操作不会报错,在dom树中也可以找到,但是会不会被显示出来。显示出来的效果是: 屏幕录制 2020-07-08 下午6.47.59.mov (803.24KB)

  • 最少代码复现demo:把上面codepen中的 clearInterval 去掉

  • 解决方法:可以通过设定最大值,接近超过行数的时候就新增一个容器。
    • 不足:在更换容器的那个节点,会丢失上下文高度,会出现一个很明显的拼接感。