Vue实现无限加载瀑布流

本文实例为大家分享了Vue实现无限加载瀑布流的具体代码,供大家参考,具体内容如下

我做的这个瀑布流放在了一个嵌套页面里,就是类似管理后台的main content中,如果要改成全屏的也很方便,其实更容易些,因为会避开一些在元素上使用onScroll的坑。

通过这个瀑布流,可以掌握以下几个知识点:

1、在元素上监听scroll事件,相对直接在window上监听麻烦一点点;
2、image.onload事件;
3、promiseAll;
4、vue 的 transition-group

这里使用了mockjs来模拟图片数据,然后通过axios来调用图片数据,也可使用其他数据源。

通过计算图片高度,判断把图片加载到哪一列。
如果屏幕还有空余,那就继续加载。
无限滚动加载。
屏幕resize这块没有做,后期可以加上去。

直接贴代码,有问题欢迎切磋。

<template>
  <div class="waterfall wf-wrap" ref="waterfall" @scroll="onScroll">
    <ul>
      <transition-group name="list" tag="li">
        <li
          v-for="(item,index) in waterfallList"
          :key="index"
          class="wf-item"
          :style="{top:item.top+ 'px',left:item.left+'px', width:item.width+'px', height:item.height + 'px'}"
        >
          <img :src="item.src" />
        </li>
      </transition-group>
    </ul>
  </div>
</template>
<script>
import { getList } from "@/api/demo";

export default {
  name: "Waterfall",
  data() {
    return {
      waterfallList: [],

      waterfallCol: 5,
      colWidth: 236,
      marginRight: 10,
      marginBottom: 10,
      colHeights: [],

      listQuery: {
        page: 1,
        limit: 5,
        sort: "+id"
      },
      loading: false,
      show: true
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
      // 初始化时,每栏高度都为0
      this.colHeights = new Array(this.waterfallCol);
      for (let i = 0; i < this.colHeights.length; i++) {
        this.colHeights[i] = 0;
      }
      this.colWidth =
        (this.$refs.waterfall.clientWidth -
          (this.waterfallCol - 1) * this.marginRight) /
        this.waterfallCol;
      this.loadImgs();
    },

    loadImgs() {
      this.loading = true;
      // 从api获取数据
      getList(this.listQuery).then(res => {
        let images = res.data.items;
        let promiseAll = [],
          imgs = [],
          total = images.length;

        for (let i = 0; i < total; i++) {
          promiseAll[i] = new Promise(resolve => {
            imgs[i] = new Image();
            imgs[i].src = images[i].image_uri;
            imgs[i].onload = () => {
              let imgData = {};
              imgData.height = (imgs[i].height * this.colWidth) / imgs[i].width;
              imgData.width = this.colWidth;
              imgData.src = images[i].image_uri;
              this.waterfallList.push(imgData);
              this.rankImgs(imgData);
              resolve(imgs[i]);
            };
          });
        }
        Promise.all(promiseAll).then(() => {
          this.loading = false;
          this.loadMore();
        });
      });
    },

    loadMore() {
      if (
        this.$refs.waterfall.clientHeight + this.$refs.waterfall.scrollTop >
          this.filterMin().minHeight &&
        this.loading == false
      ) {
        this.loading = true;
        setTimeout(() => {
          this.loadImgs();
        }, 200);
      }
    },

    rankImgs(imgData) {
      let min = this.filterMin();
      imgData.top = min.minHeight;
      imgData.left = min.minIndex * (this.colWidth + this.marginRight);

      this.colHeights[min.minIndex] += imgData.height + this.marginBottom;
    },

    filterMin() {
      let minHeight = Math.min.apply(null, this.colHeights);
      return {
        minHeight: minHeight,
        minIndex: this.colHeights.indexOf(minHeight)
      };
    },

    onScroll() {
      this.loadMore();
    }
  }
};
</script>

<style lang="scss" scoped>
ul li {
  list-style: none;
}

.wf-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: scroll;
}
.wf-item {
  position: absolute;
}
.wf-item img {
  width: 100%;
  height: 100%;
}
.list-enter-active,
.list-leave-active {
  transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {
  opacity: 0;
  transform: translateY(30px);
}
</style>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • vue瀑布流组件实现上拉加载更多

    最近在做移动端h5页面,所以分页什么的就不能按照传统pc端的分页器的思维去做了,这么小的屏幕去点击也不太方便一般来讲移动端都是上拉加载更多,符合正常使用习惯. 首先简单写一下模板部分的html代码,,很简单清晰的逻辑: <template> <div class="loadmore"> <div class="loadmore__body"> <slot></slot> </div> <d

  • Vue瀑布流插件的使用示例

    我自己写的一个的Vue瀑布流插件,列数自适应,不用设置每个卡片的高度. 测试页面:Page.vue 模板页面:WaterFollow.vue 和 WFColumn.vue 在Page.vue中,修改itemW的值,设置每列的最小宽度.例如:itemW="200"(意为200px).list为数组.高度不用设置,:style="{height:item+'px'}"是我为了创造卡片高度加上去的,不加就显示卡片的原来大小. 经测试,created加载数据正常,mount

  • vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多(步骤详解)

    一.思路分析和效果图 用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果.然后针对这几个效果的实现,捋下思路: 根据加载数据的顺序,依次追加标签展示效果: 选择哪种方式实现瀑布流,这里选择绝对定位方式: 关键问题:由于每张图片的宽高不一样,而瀑布流中要求所有图片的宽度一致,高度随宽度等比缩放.而且由于图片的加载是异步延迟.在不知道图片高度的情况下,每个图片所在的item盒子不好绝对定位.因此在渲染页面前先获取所有图片的高度,是解决问题的关键点!这里选择用JS中的Im

  • vue.js组件vue-waterfall-easy实现瀑布流效果

    想必大家应该很多都已经习惯了jquery的DOM操作,jquery的瀑布流实现起来也很容易. 但是,随着时代的发展,随着时代的进步..... 算了算了,扯远了,既然能找到这儿来,肯定是在vue.js上已经有一定的基础了,咱们废话不多说,直接进入主题. vue-waterfall-easy easy! easy! easy! 重要的事情说三遍!!! 所以说,咱们今天用到的不是大家熟知的vue-waterfall,而是vue-waterfall-easy: 一.获取vue-waterfall-eas

  • vue实现简单瀑布流布局

    vue简单实现瀑布流布局的一种方式(vue瀑布流组件),供大家参考,具体内容如下 vue中的瀑布流布局组件 需求:图片容器宽度固定,高度根据图片自适应,图片一行不能排列时候,换行依次从左往右排列.(瀑布流概念) 另外结合vue-lazy实现懒加载 ( npm i vue-lazyload --save-dev) 使用也很简单,在需要懒加载的img标签上将:src换成v-lazy 父组件传递数据: waterfallData:[ { e_img: "test.jpg", // 图片 e_

  • vue实现瀑布流组件滑动加载更多

    建议先看vue瀑布流组件上拉加载更多再来食用本文,如果直接想看源码文末就是~ 文末新增组件优化,之所以没有删优化前的代码是想让以后自己还能看到走过的路. 上一篇讲到在项目中使用上拉加载更多组件,但是由于实际项目开发中由于需求变更或者说在webview中上拉加载有些机型在上拉时候会把webview也一起上拉导致上拉加载不灵敏等问题,我们有时候也会换成滑动到底部自动加载的功能. 既然都是加载更多,很多代码思想势必相似,主要区别在于上拉和滑动到底部这个操作上,所以,我们需要注意: 1.上拉加载是poi

  • 通过vue写一个瀑布流插件代码实例

    这篇文章主要介绍了通过vue写一个瀑布流插件代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 效果如图所示: 采用了预先加载图片,再计算高度的办法..网络差的情况下,可能有点卡 新建 vue-water-easy.vue 组件文件 <template> <div class="vue-water-easy" ref="waterWrap"> <div v-for="(i

  • Vue实现无限加载瀑布流

    本文实例为大家分享了Vue实现无限加载瀑布流的具体代码,供大家参考,具体内容如下 我做的这个瀑布流放在了一个嵌套页面里,就是类似管理后台的main content中,如果要改成全屏的也很方便,其实更容易些,因为会避开一些在元素上使用onScroll的坑. 通过这个瀑布流,可以掌握以下几个知识点: 1.在元素上监听scroll事件,相对直接在window上监听麻烦一点点: 2.image.onload事件: 3.promiseAll; 4.vue 的 transition-group 这里使用了m

  • 基于JavaScript实现无限加载瀑布流

    本文实例为大家分享了JS实现无限加载瀑布流展示的具体代码,供大家参考,具体内容如下 1.在外层的div中,插入4个ul,ul左浮动 2.每次在创建节点之后,插入节点之前,要获取每个ul的高度,找到最小的高度,然后将新创建的li节点插入该ul中 3.当文档的高度 - 文档的可视高度 <= 鼠标的滑动距离时 开始继续创建节点 代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8">

  • jQuery实现动态加载瀑布流

    jquery实现瀑布流,供大家参考,具体内容如下 案例分析 首先,它的每个图片是等宽的 其次,除第一排正常显示其余的图片都会显示在上一排中高度最小的那个图片的下面 最后,就是根据最矮图片所在位置的宽高来,决定绝对定位设置图片显示的位置 效果图 实现步骤 html结构 <div class="container"> <div class="box"> <div class="content"><img sr

  • Vue.js实现无限加载与分页功能开发

    本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景--分页/无限加载,帮助读者更好的理解Vue.js中的一些设计思想.与许多Todo List类的入门教程相比,更全面的展示使用Vue.js完成一个需求的思考过程:与一些构建大型应用的高阶教程相比,又更专注于一些零碎细节的实现,方便读者快速掌握.致用. 需求分析 当一个页面中信息量过大时(例如一个新闻列表中有200条新闻需要展示),就会产生问题,例如: >数据量过大,影响加载速度 >用户体验差,很难定位到之前自己看过的某篇文章 >

  • 实现一个简单的vue无限加载指令方法

    vue 中的自定义指令是对底层 dom 进行操作,下面以实现滚动到底部加载数据,实现无限加载来介绍如何自定义一个简单的指令. 无限加载的原理是通过对滚动事件的监听,每一次滚动都要获取到已滚动的距离,如果滚动的距离加上浏览器窗口高度,会大于等于内容高度,就触发函数加载数据. 先介绍不使用 vue 的情况如何实现无限加载. 不使用框架 首先是html: <!DOCTYPE html><html lang="en"> <head><meta char

  • Vue下滚动到页面底部无限加载数据的示例代码

    看到一篇Implementing an Infinite Scroll with Vue.js, 觉得挺实用的就看了下, 顺便简单翻译了一下给需要的人参考. 从这个项目中可以加深对Vue的生命周期的理解, 何时开始axios请求, 如何结合Vue使用原生js来写scroll事件等等, 我这里主要是对原文的重点提取和补充 本文技术要点 Vue生命周期 axios简单用法 moment.js格式化日期 图片懒加载 结合原生js来写scroll事件 请求节流 创建项目 首先创建一个简单的vue项目 #

  • Vue中的无限加载vue-infinite-loading的方法

    本文介绍了Vue中的无限加载vue-infinite-loading的方法,分享给大家,具体如下: 注意:vue-infinite-loading2.0只能在Vue.js2.0中使用.如果你想在Vue.js1.0中使用,请安装vue-infinite-loading1.3版本 如何安装 npm install vue-infinite-loading --save 导入方式 es6模块导入方式 import InfiniteLoading from 'vue-infinite-loading';

  • Vue实现一个无限加载列表功能

    一个需要判断的地方就是加载中再次触发滚动的时候,不要获取数据. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>列表无限加载</title> <style> * { margin: 0; padding: 0; } li { height: 50px; border-bottom: 1px s

  • vue 使用vant插件做tabs切换和无限加载功能的实现

    样例: 1.创建vue项目,不再详述 2.引入vant 之前用过很多插件做这个功能,但是效果都不尽人意,出现各种问题,直到遇到vant这个插件,完美的解决了这些小问题,如有问题,欢迎联系我 安装依赖 npm i vant -S 在main.js中引入 import Vant from 'vant'; import 'vant/lib/index.css'; Vue.use(Vant); 3.在页面中使用 官方写的比我写的好多了,大家可以借鉴,看源代码可能比官方给的文档更直观 官方文档 我在文件中

  • Vue简易版无限加载组件实现原理与示例代码

    目录 背景 实现功能 Props 使用 组件实现 scroll 事件 $emit 发射事件和 props 回调函数的区别 总结 背景 遇到的两个问题:scroll 事件不触发.如何将 loading 状态放在无限加载组件中进行管理. 无限加载组件在展示列表页数据时比较常见.特别是在 H5 列表页中,数据比较多,需要做分页,无限加载组件就是一个非常好的选择. 当列表页数据比较多时,一次性从服务端拿到所有的数据会比较耗时,长时间不展示列表数据,比较影响用户体验.所以对于一般的长列表数据,都会做分页.

随机推荐