Use flex para implementar el flujo de cascada

prefacio

Hola a todos, esta es la tienda de Fujiwara Tofu, dije que escribiría un artículo para registrar la realización del flujo de la cascada, pero se ha retrasado hasta ahora, lo compensaré cuando tenga tiempo en la tarde.

que es cascada

Flujo de cascada, también conocido como diseño de flujo de cascada. Es un diseño de página de sitio web relativamente popular, y su rendimiento visual es un diseño desigual de varias columnas A medida que la barra de desplazamiento de la página se desplaza hacia abajo, este diseño continuará cargando bloques de datos y agregándolos a la cola actual.

Características:

  • ancho fijo, altura variable
  • diseño irregular

Use flex para implementar el flujo de cascada

El efecto logrado es un flujo de cascada dividido en dos columnas, y deslizando hacia abajo cargará los datos de la página siguiente y lo cargará en la página.

Implementación de estilo

<view class="blessing-con">
  <view class='blessing-con-half'>
    <view id="leftHalf">
      <view class="blessing-con-half-item" :class="bgColor[index % 3]"
        v-for="(item, index) in newBlessingWordsList1" :key="index">
        <view class="item-con">
        </view>
      </view>
    </view>
  </view>
  <view class='blessing-con-half'>
    <view id="rightHalf">
      <view class="blessing-con-half-item" :class="bgColor[(index + 1) % 3]"
        v-for="(item, index) in newBlessingWordsList2" :key="index">
        <view class="item-con"></view>
      </view>
    </view>
  </view>
</view>
<view class="blessing-more" @click="handlerMore">
  <image v-if="hasWallNext" class="more-icon"
    src="xx/blessingGame/arr-down.png">
  </image>
  <view class="blessing-more-text">{{ blessingStatus }}</view>
</view>

.blessing-con define el contenedor exterior como un diseño flexible y establece la alineación del eje principal en el espacio entre

.blessing-con-half define el estilo del contenedor en los lados izquierdo y derecho

.blessing-con-half-item define el estilo de cada caja pequeña

.blessing-con {
  padding: 32rpx 20rpx;
  display: flex;
  justify-content: space-between;
  height: 1100rpx;
  overflow-y: auto;
  .blessing-con-half {
    width: 320rpx;
    height: 100%;
    box-sizing: border-box;
    .blessing-con-half-item {
      width: 100%;
      height: auto;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
      margin: 0 0 24rpx;
      position: relative;
    }
  }
}

Aquí, el color de fondo de cada cuadro pequeño es del orden azul-amarillo-rojo, y se agrega una imagen irregular en la parte superior del cuadro a través de una pseudoclase para lograr un efecto irregular.

bgColor: ['blueCol', 'yellowCol', 'pinkCol'], //祝福墙背景
// 不同颜色
.blessing-con-half-item {
    &.pinkCol {
      &::before {
        .setbg(320rpx, 16rpx, 'blessingGame/pink-bg.png');
      }
      .item-con {
        background: #FFE7DF;
      }
    }
  
    &.yellowCol {
      &::before {
        .setbg(320rpx, 16rpx, 'blessingGame/orange-bg.png');
      }
      .item-con {
        background: #fff0e0;
      }
    }
  
    &.blueCol {
      &::before {
        .setbg(320rpx, 16rpx, 'blessingGame/blue-bg.png');
      }
      .item-con {
        background: #e0f7ff;
      }
    }
  }
}

realización de funciones

Defina dos matrices en datos para almacenar los datos de las listas izquierda y derecha

data(){
  return{
    blessingWordsList: [],// 祝福墙数据
    newBlessingWordsList: [],
    newBlessingWordsList1: [],//左列表
    newBlessingWordsList2: [],//右列表
    isloading:false,//是否正在加载
    hasWallNext:false,//是否有下一页
    leftHeight: 0,//左高度
    rightHeight: 0,//右高度
    blessingWordsCount: 0,//计数器
    isActive: 0, //tab初始化索引
    timer:null,//定时器
  }
}

Datos de la lista de solicitudes de la interfaz de llamadas

  • La primera solicitud de datos debe inicializar los datos de la lista y los contadores.
  • El temporizador debe iniciarse después de cada solicitud.
// 获取祝福墙列表(type=1则请求下一页)
  async getBlessingWall(type = 0) {
    try {
      let res = await api.blessingWall({
        activityId: this.activityId,
        pageNum: this.pageWallNum,
        pageSize: this.pageWallSize
      })
      this.isloading = false
      if (res.code == 1 && res.rows) {
        let list = res.rows
        this.blessingWordsList = (type==0 ? list : [...this.blessingWordsList, ...list])
        if (this.blessingWordsList.length > 0 && !this.timer && this.isActive == 1) {
            if(this.pageWallNum == 1){
                    this.newBlessingWordsList = []
                    this.newBlessingWordsList1 = []
                    this.newBlessingWordsList2 = []
                    this.blessingWordsCount = 0
            }
            this.start()
        }
        // 处理请求下一页的情况
        if (type == 1) {
          this.start()
        }
        this.hasWallNext = res.hasNext
        if (!this.hasWallNext) {
          this.blessingStatus = "没有更多了哟"
        } else {
          this.blessingStatus = "点击加载更多"
        }
      }
    } catch (error) {
      console.log(error)
    }
  },
// 加载更多
 async handlerMore() {
  if (this.hasWallNext && !this.isloading) {
    this.isloading = true
    this.pageWallNum++
     await this.getBlessingWall(1)
  }
},

Inicie un temporizador para agregar dinámicamente datos a las listas izquierda y derecha

start() {
  // 清除定时器
  clearInterval(this.timer)
  this.timer = null;
  
  this.timer = setInterval(() => {
    let len = this.blessingWordsList.length
    if (this.blessingWordsCount < len) {
      let isHave = false
      // 在列表中获取一个元素
      let item =this.blessingWordsList[this.blessingWordsCount]
      // 判断新列表中是否已经存在相同元素,防止重复添加
      this.newBlessingWordsList.forEach((tmp)=>{
        if(tmp.id == item.id){
          isHave = true
        }
      })
      // 如果不存在
      if (!isHave) {
        this.newBlessingWordsList.push(item)//添加该元素
        this.$nextTick(() => {
          this.getHei(item)//添加元素到左右列表
        })
      }
    } else {
      // 遍历完列表中的数据,则清除定时器
      clearInterval(this.timer)
      this.timer = null;
    }
  }, 10)
}

Calcule la altura de los contenedores izquierdo y derecho actuales y determine de qué lado se deben agregar los datos

  • Use el método uni-app para obtener los objetos dom de los contenedores izquierdo y derecho, y luego obtenga sus alturas actuales
  • Compare las alturas izquierda y derecha e inserte dinámicamente datos en las dos matrices
  • Cada vez que se inserta un dato, el contador +1
getHei(item) {
  const query = uni.createSelectorQuery().in(this)
  // 左边
  query.select('#leftHalf').boundingClientRect(res => {
    if (res) {
      this.leftHeight = res.height
    }
    // 右边
    const query1 = uni.createSelectorQuery().in(this)
    query1.select('#rightHalf').boundingClientRect(dataRight => {
      if (dataRight) {
        this.rightHeight = dataRight.height != 0 ? dataRight.height : 0
        if (this.leftHeight == this.rightHeight || this.leftHeight < this.rightHeight) {
          // 相等 || 左边小  
          this.newBlessingWordsList1.push(item)
        } else {
          // 右边小
          this.newBlessingWordsList2.push(item)
        }
      }
      this.blessingWordsCount++
    }).exec()
  }).exec()
},

Hay un punto a tener en cuenta aquí: al llamar al método de inicio, debe asegurarse de que la página represente los elementos de los contenedores izquierdo y derecho, de lo contrario no obtendrá la altura del contenedor.

Por ejemplo, mi proyecto tiene cambio de pestaña

Al ingresar a la página, los datos se solicitarán una vez. En este momento, debido a que el estado inicial de la pestaña es 0, no se llamará al método de inicio. Cuando la pestaña se cambia a 1, se llamará al método de inicio para comenzar a calcular la altura.

data(){
  return{
    isActive: 0, //tab初始化索引
    timer:null,//定时器
  }
}
async onLoad(options) {
  this.getBlessingWall()
}
// tab选项卡切换
tabClick(index) {
  this.isActive = index
  this.isLoaded = false;
  if (this.blessingWordsList.length > 0 && !this.timer && this.isActive == 1) {
    if(this.pageWallNum == 1){
      this.newBlessingWordsList = []
      this.newBlessingWordsList1 = []
      this.newBlessingWordsList2 = []
      this.blessingWordsCount = 0
    }
    this.start()
  }
},

por fin

Esta vez elegí flex para realizar el flujo de la cascada. Hay varias otras formas de realizar el flujo de la cascada. Si hay una posibilidad más tarde, agregaré varios otros métodos. Si está interesado, ¡puede prestar atención!

Supongo que te gusta

Origin juejin.im/post/7260713996165021754
Recomendado
Clasificación