H5移动端vue-masonry + van-list实现瀑布流懒加载效果

首先安装这两个库(vue-masonry, vant2):

npm install vue-masonry --save
npm i vant@latest-v2 --save

main.js中全局注册:

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Vant from 'vant'
import 'vant/lib/index.css'
import {VueMasonryPlugin} from 'vue-masonry';
import '@/assets/global.css'

Vue.config.productionTip = false

Vue.use(Vant)
Vue.use(VueMasonryPlugin)

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

在对应组件使用:

<!--结构-->
<template>
  <van-list v-model="loading" :finished="finished" finished-text="我是有底线的" @load="onLoad" :immediate-check="false">
    <van-cell>
      <div v-masonry transition-duration="0s" item-selector=".film-item">
        <div v-masonry-tile class="film-item" v-for="(item, index) in filmList" :key="item.id">
          <img :src="item.poster">
          <div class="film-information-container">
            <div class="film-actors-container">
              <div class="film-actors">
                主演:{{ filteredActors(item.actors, index) }}
              </div>
            </div>
            <button class="buy-tickets">购票</button>
          </div>
        </div>
      </div>
    </van-cell>
  </van-list>
</template>
// 状态
data() {
    return {
      filmList: [],
      loading: false,
      finished: false,
      curPage: 1,
      filmsTotal: 0
    }
},

总体代码(要实现懒加载需要后端对接口进行分页):

<template>
  <van-list v-model="loading" :finished="finished" finished-text="我是有底线的" @load="onLoad" :immediate-check="false">
    <van-cell>
      <div v-masonry transition-duration="0s" item-selector=".film-item">
        <div v-masonry-tile class="film-item" v-for="(item, index) in filmList" :key="item.id">
          <img :src="item.poster">
          <div class="film-information-container">
            <div class="film-actors-container">
              <div class="film-actors">
                主演:{{ filteredActors(item.actors, index) }}
              </div>
            </div>
            <button class="buy-tickets">购票</button>
          </div>
        </div>
      </div>
    </van-cell>
  </van-list>
</template>

<script>
import http from '@/utils/http.js';

export default {
  data() {
    return {
      filmList: [],
      loading: false,
      finished: false,
      curPage: 1,
      filmsTotal: 0
    }
  },

  mounted() {
    http({
      url: `/gateway?cityId=310100&pageNum=1&pageSize=10&type=1&k=908466`,
      headers: {
        'X-Host': 'mall.film-ticket.film.list'
      }
    }).then((res) => {
      this.filmsTotal = res.data.data.total;
      this.filmList = res.data.data.films;
      console.log(this.filmList);
      console.log(this.filmsTotal)
    })
  },

  methods: {
    // changeDetail (id) {
    //   this.$router.push(`/detail/${id}`)
    // },
    onLoad() {
      console.log('到底了,需要继续加载')

      // 特判,当总数据小于10条时
      if (this.filmsTotal <= 10 && this.filmsTotal !== 0) {
        this.finished = true
        return
      }

      // 判断当前页数是否等于总页数,并且初始长度不等于0,防止从详情页返回出现bug,造成误判
      if (this.curPage === Math.ceil(this.filmsTotal / 10) && this.filmsTotal !== 0) {
        this.finished = true
        return
      }

      this.curPage++
      http({
        url: `/gateway?cityId=310100&pageNum=${this.curPage}&pageSize=10&type=1&k=908466`,
        headers: {
          'X-Host': 'mall.film-ticket.film.list'
        }
      }).then((res) => {
        this.filmList = this.addNewFilmItems(res.data.data.films);
        this.filmsTotal = res.data.data.total
        this.loading = false
        console.log(this.filmList);
      })
    },

    addNewFilmItems(newFilmList) {
      return this.filmList.concat(newFilmList);
    },

    filteredActors(actors, index) {
      const actorsName = actors.map((item) => {
        return item = item.name;
      });
      
      return actorsName.join(' ');
    }
  }
}
</script>

<style lang="scss" scoped>
.van-cell {
  padding: 0.25rem 0.3rem 0.25rem 0.3rem;
}

.film-item {
  background: white;
  margin: 0.5rem;
  width: calc((100% - 2rem) / 2);
  border-radius: 0.35rem;
  box-shadow: 0 0 0 0.05rem #e7e7e7;

  img {
    width: 100%;
    object-fit: cover;
    border-radius: 0.35rem 0.35rem 0rem 0rem;
  }

  .film-information-container {
    margin: 0.45rem 0.25rem 0.45rem 0.25rem;

    .film-actors-container {
      font-size: 0.777rem;
      word-break: break-all;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-box-orient: vertical;
      /* 这里是超出几行省略 */
      -webkit-line-clamp: 2;
      overflow: hidden;
      margin: 0 0 0.5rem 0;
    }

    .buy-tickets {
      background: #6b78fb;
      font-size: 0.666rem;
      color: white;
      width: 80%;
      height: 1.2rem;
      border-radius: 0.6rem;
      border-style: none;
      transform: translateX(12.5%);
    }
  }
}
</style>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值