继上一篇v-for 动态生成盒子解决动态换行问题

960 阅读4分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

前言

前几天写了一篇 “ vue 中 v-for 动态生成盒子换行排列布局效果 ” 的文章来大概讲解了一下多个大小不同的盒子的动态生成。当时留下了一点问题,就是在动态生成每个 ul 的时候,之前是把每个 ul 中的 li 的个数定死了,这几天想了一下优化的方法,具体想了两种,大概粗略的实现了这个需求

问题所在

按理来说,每个ul当中的li的个数应该是不确定的,根据数组中不同的组合方案,生成的li数量应该也要是不同的,就像下图的两个ul。

捕获.PNG

很明显能看出,第一个ul是刚好的8个li,但是第二个ul就只有7个li,这显然要上一篇里的算法页面就会出现问题,接下去就说一下,我现在用了什么样的办法来解决这个需求。

解决方法

第一个

首先今天想到的第一个方法是:直接建立一个map表去匹配每一种情况,比方说碰到三个1*1的盒子就进行换行,或者一个1*2加上一个1*1换行。当然这种方法需要在map当中添加很多的数据,因为三种盒子动态生成将会有很多不同的情况,但是如果能够保证,盒子动态生成,但是它生成的组合排列一定是正确的,不会出现一行之中有放不下的盒子跳到下一行去的情况:

image.png

在这个前提下,这个匹配表就能减少很多的数据

itemSegmentation(items) {
      let lineFeedTable = new Map([
        ["smallsmallsmall", 1],
        ["smallmedium", 1],
        ["mediumsmall", 1],
        ['smallsmalllarge',2],
        ['largesmallsmall',2],
      ]);
      let temporaryArray = '';
      let splitItem = [];
      let line = 0;
      let idx = 0;
      items.forEach((item, index) => {
        temporaryArray += item.size;
        if(lineFeedTable.get(temporaryArray) == 1){
          line++
          temporaryArray = '';
        }else if(lineFeedTable.get(temporaryArray) == 2){
          line += 2;
          temporaryArray = '';
        }
        if (!splitItem[idx]) splitItem[idx] = [];
        splitItem[idx].push(item);
        if(line == 4){
          idx ++
          line = 0;
        }
      });
      return splitItem;
    },

上面可以看到我将盒子的大小定位 small ,medium 和 large ,用一个字符串记录出现过的盒子,当字符串串接起来满足 map 表中的某一项的时候,自动转化为需要增加的行数,当行数满4行就换一个ul并且重新计算行数。

第二个

第二种方法就提供一个思路,我们可以通过一个循环判断,当循环碰到了1*2的盒子,就先去找它前面有没有1*1,没有的话就去找后面,再没有的话,就说明这个1*2是自己单独一行,以此类推,2*2因为没办法和1*2放在同一行,使用也是前后去找1*1的盒子,然后两种找到了或者没找到,都要在行数上对应的加1或加2,再者就是定一个数判断1*1出现的个数,当它连续三次出现的时候,行数加一,计数器清零。

比方说下面这个 array 如果是我们传进来的 item ,然后对他进行 foreach 循环,当你循环到1*1时计数器加一然后下一个,循环到了1*2就去判断前面有没有1*1,有的话就把他们两一起拿出来,没有就去判断后面有没有1*1,同理,有的话就拿出来。

image.png

0f5ed4e9148942099693499736d46a42_tplv-k3u1fbpfcp-watermark.png

  • 先判断前面有没有小盒子,有的话就将他们两个拿出来,没有就去判断后面,有的话就拿出来,前后都没有,就单独把2拿出来,然后 line 加一,计数器清零。

  • 2和3同理,计数器加一跳过,因为没有到三,所以不做操作。

image.png

  • 到大盒子的时候也是先去判断前面有没有小盒子,因为小盒子的计数器只能是1或者2(3就直接换行清零了)所有大盒子只要判断前面还有没有小盒子就可以,不用在意小盒子是一个或者两个,反正都是放得下的。之后再来判断后面有没有小盒子。

image.png

  • 比方说前面没有小盒子,先去判断后一位是小盒子的话,再去判断后二位是不是小盒子,然后取出。

总结

上面总结了我自己今天想的两种解决上次遗留下来的问题的方法,具体使用会不会因为奇怪的数据出现 bug 暂时还没有去尝试,如果发现这些方法不对的地方,欢迎提出,有更好的解法也可以一起讨论。