26

vue.js + mint-ui 在移动端实现上拉加载-下拉刷新效果

 5 years ago
source link: https://fy98.com/2018/06/15/vue-mint-ui-pullup-pulldown/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

开发移动端 webApp 经常会遇到列表页需要下拉刷新(pull-down)和上拉加载更多(pull-up)的场景,这里介绍一下使用 Vue.js 开发时配合 Mint-UI 的 <Loadmore /> 组件实现这一功能。

Mint UI 的文档写的还是比较详细的,如果有文档看不懂地方,结合github上源代码具体实现喝issue提问,基本就能解决9成问题了。

根据 官方文档 介绍,快速安装 Mint Ui,然后引入到页面中。

template 如下:

<template>
  <div class="list">
    <x-header>上拉加载,下拉刷新</x-header>
    <div class="page-loadmore-wrapper" ref="wrapper" :style="{ height: wrapperHeight + 'px' }">
      <mt-loadmore
        :top-method="loadTop"
        :bottom-method="loadBottom"
        :bottom-all-loaded="allLoaded"
        :auto-fill="false"
        @top-status-change="handleTopChange"
        @bottom-status-change="handleBottomChange"
        ref="loadmore">
        <ul>
          <li class="page-loadmore-listitem" :key="item" v-for="item in list">{{ item }}</li>
        </ul>
        <div slot="top" class="mint-loadmore-top">
          <span v-show="topStatus !== 'loading'" :class="{ 'is-rotate': topStatus === 'drop' }">↓</span>
          <span v-show="topStatus === 'loading'">
            <mt-spinner type="snake"></mt-spinner>
          </span>
        </div>
        <div slot="bottom" class="mint-loadmore-bottom">
          <span v-show="bottomStatus !== 'loading'" :class="{ 'is-rotate': bottomStatus === 'drop' }">↑</span>
          <span v-show="bottomStatus === 'loading'">
            <mt-spinner type="snake"></mt-spinner>
          </span>
        </div>
      </mt-loadmore>
    </div>
  </div>
</template>

script 代码如下:

<script>
import { Spinner } from 'mint-ui';

export default {
  data() {
    return {
      list: [],
      topStatus: '',
      bottomStatus: '',
      wrapperHeight: 0,
      allLoaded: false,
    }
  },
  components: {
    'mt-spinner': Spinner, // 或者使用 Vue.component(Spinner.name, Spinner) 注册组件
    'mt-loadmore': Loadmore,
  },
  methods: {
    handleTopChange(status) {
      console.log(status);
      this.topStatus = status;
    },
    handleBottomChange(status) {
      console.log('handleBottomChange ', status);
      this.bottomStatus = status;
    },
    loadTop() {
      console.log('loadTop');
      setTimeout(() => {
        let firstValue = this.list[0];
        for (let i = 1; i <= 10; i++) {
          this.list.unshift(firstValue - i);
        }
        this.$refs.loadmore.onTopLoaded();
        console.log('load top end');
      }, 2000);
    },
    loadBottom() {
      setTimeout(() => {
        let lastValue = this.list[this.list.length - 1];
        if (lastValue <= 60) {
          for (let i = 1; i <= 10; i++) {
            this.list.push(lastValue + i);
          }
        } else {
          this.allLoaded = true; // 若数据已全部获取完毕
        }
        this.$refs.loadmore.onBottomLoaded();// 固定方法,查询完要调用一次,用于重新定位
        console.log('loadBottom end, this.allLoaded = ', this.allLoaded);
      }, 1500);
    },
  },
  created() {
    for (let i = 0; i < 20; i++) {
      this.list.push(i);
    }
  },
  mounted() {
    this.wrapperHeight = document.documentElement.clientHeight - this.$refs.wrapper.getBoundingClientRect().top;
  }
}
</script>

style 代码如下:

<style lang="scss">
body {
  margin: 0;
  background-color: #fafafa;
}
ul,li{ padding:0;margin:0;list-style:none};
.page-loadmore-wrapper {
  overflow: scroll; // 很重要
  -webkit-overflow-scrolling : touch; // 解决view滑动速度慢或者卡顿问题
}
.page-loadmore-listitem {
  height: 50px;
  line-height: 50px;
  border-bottom: 1px solid #eee;
}
.mint-loadmore-top {
  span {
    display: inline-block;
    transition: .2s linear;
    vertical-align: middle;
  }
  span.is-rotate {
    transform: rotate(180deg);
  }
}
.mint-loadmore-bottom {
  span {
    display: inline-block;
    transition: .2s linear;
    vertical-align: middle;
    }
    span.is-rotate {
      transform: rotate(180deg);
    }
}
</style>

预览一下效果:

ZjaiYvj.gif

遇到的问题

  1. pull-up事件 loadBottom 无法触发,pull-down事件 loadTop 却正常,原因是因为没有限制 <mt-loadmore > 的父组件高度,同时也需要给父容器添加 overflow:scroll 属性
  2. 在手机上测试发现 wrapper 容器在滑动时有些慢、卡顿的现象,添加css属性 -webkit-overflow-scrolling : touch; 可解,原因是启用了硬件加速
  3. wrapperHeight 高度一定要小于列表的高度才可以 pull up

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK