vue中一个组件实现多种样式(列表布局、网格布局、瀑布流布局)

2,366 阅读1分钟

最近有一个需求,用户可以动态切换页面的布局 分别是1.列表布局 2.网格布局 3.瀑布流布局

其中瀑布流是最难实现的一种

1、实现瀑布流的思路

随机生成图片高度,使用absolute布局,使用两个变量来分别记录左边的高度以及右边的高度,当左边的高度大于右边的高度的时候,下一个item就会push进右边,相对应的right为0px,top为右边高度的值。反之则push进左边。效果图如下👇

    1.对图片随机在一定范围内生成高度,并且用一个数组来记录生成的高度
    /**
     * 返回随机的图片高度
     */
    imgHeight() {
      let result = Math.floor(
        Math.random() * (this.MAX_IMG_HEIGHT - this.MIN_IMG_HEIGHT) +
          this.MIN_IMG_HEIGHT
      );
      return result;
    },
    /**
     * 根据随机高度,生成图片样式数据
     */
    initImgStyles() {
      this.goodsData.forEach(item => {
        this.imgStyles.push({
          height: this.imgHeight() + "px"
        });
      });
    },
    2.通过ref拿到item的clientHeight,并且定义两个变量,一个记录左边的高度,一个记录右边的高度,
      当左边高度大于右边高度的时候,下一个item则会放在右边,把最终得出来的记录每一个item的样式数组绑定
      在item中,使用绑定时需要传递下表获取对应的style
    /**
     * 瀑布流布局
     */
    initWaterfall() {
      let $goodsItems = this.$refs.goodsItem;
      if (!$goodsItems) return;
      // 左边高度, 右边高度
      let leftHeightTotal = 0,
        rightHeightTotal = 0;
      $goodsItems.forEach(($el, index) => {
        let goodsItemStyle = {};
        let elHeight = $el.clientHeight + this.itemMarginBottomSize;
        if (leftHeightTotal <= rightHeightTotal) {
          goodsItemStyle = {
            left: "0px",
            top: `${leftHeightTotal}px`
          };
          leftHeightTotal += elHeight;
        } else {
          goodsItemStyle = {
            right: "0px",
            top: `${rightHeightTotal}px`
          };
          rightHeightTotal += elHeight;
        }

        this.goodsItemStyles.push(goodsItemStyle);
      });
      this.$forceUpdate();
      this.goodsViewHeight =
        leftHeightTotal > rightHeightTotal
          ? leftHeightTotal
          : rightHeightTotal + "px";
    },

这样子瀑布流就可以实现了,接下来实现的是如何通过参数来动态改变样式来实现不同的布局

    1.父组件通过传递不同的参数,来代表不同的样式
    2.首先对于页面定义最基本的样式,不同的布局样式我们使用:class来进行动态改变
    3.监听父组件传进来的值,来重新初始化布局
    1.网格布局,并不需要使用js来进行判断,样式比较简单,如下👇
    // ps:笔者使用的是scss预编译
    .goods-grid {
      position: relative;
      margin: $marginSize;
      display: flex;
      overflow: hidden;
      flex-wrap: wrap;
      justify-content: space-between;
      &-item {
        width: 48%;
        border-radius: $radiusSize;
        margin-bottom: $marginSize;
        overflow: hidden;
        .goods-item-img {
          width: 100%;
        }
      }
    }

grid网格布局图片如下👇

列表布局相对简单,所以就不再这里贴代码了。最后如果你觉得喜欢或者对你有用,记得点赞哦~