使用Mint-UI的Loadmore实现上拉加载更多和下拉刷新

最近用 mint-ui 实现了上拉加载更多下拉刷新,正好今天有空就把实现过程都给记录下来,下面我准备来个小白教程。

我这个利用vue单页和普通页面方式展示。

1、首先用脚手架 vue-cli 搭建环境(这里我百度找了一个算看到舒服的教程,仅供参考)

2、Mint-UI (这里官网快速上手,可以根据里面的教程快速的添加 mint-ui  到项目中去,图片和代码看都有,推荐自己看图手敲代码)

 

.babelrc文件

 

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime",
    ["component", 
      [
        {
          "libraryName": "mint-ui",
          "style": true
        }
      ]
    ]
  ]
}

 

 

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
import { Loadmore } from 'mint-ui'

Vue.component(Loadmore.name, Loadmore);

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    components: { App },
    template: '<App/>'
})

 

HelloWorld.vue(页面就直接上代码截图太长了,里面用的图片[chicken-wings.jpg, swine-fever.jpg]我是百度的需要图片的自己找, 另外这两张图都是直接放在 static 文件夹)

<template>
  <div class="hello">
    <mt-loadmore
      :top-method="loadTop"
      :bottom-method="loadBottom"
      :bottom-all-loaded="allLoaded"
      @top-status-change="handleTopChange"
      @bottom-status-change="handleBottomChange"
      :autoFill="false"
      ref="loadmore"
    >
      <ul>
        <li class="order-intr clearfix" v-for="(item, index) in list" :key="index">
          <img class="fl" :src="item.cover">
          <div class="title fl">
            <h3>{{item.title}}</h3>
            <p>数量:{{item.num}}</p>
          </div>
          <b class="fr price">¥{{item.price}}</b>
        </li>
      </ul>
      <div slot="top" class="mint-loadmore-top">
        <span v-show="topStatus !== 'loading'" :class="{ 'rotate': topStatus === 'drop' }">松手释放↓</span>
        <span v-show="topStatus === 'loading'">加载中</span>
      </div>
      <div slot="bottom" class="mint-loadmore-bottom">
        <span
          v-show="bottomStatus !== 'loading'"
          :class="{ 'rotate': bottomStatus === 'drop' }"
        >松手释放↑</span>
        <span v-show="bottomStatus === 'loading'">加载中</span>
      </div>
      <p v-if="allLoaded" class="to-the-bottom">我是有底线的</p>
    </mt-loadmore>
  </div>
</template>
<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      topStatus: "",
      bottomStatus: "",
      allLoaded: false,
      list: [],
      mockArr: [],
      number: 0
    };
  },
  created() {
    // ajax 模拟初始加载, 使用定时器默认ajax加载
    let timer = setTimeout(_ => {
      clearTimeout(timer);
      this.loadData('refresh');
    }, 200);
  },
  methods: {
    loadData(p_status) {
      // 第一次加载或者下拉刷新最新数据
      if (p_status === "refresh") {
        this.mockArr = [];
      }
      for (let i = 0; i < 5; ) {
        let obj = {
          cover: "./static/chicken-wings.jpg",
          title: "奥尔良鸡中翅饭",
          num: 1,
          price: 14.88
        };
        obj["id"] = this.mockArr.length + 1;
        if (i % 2) {
          obj["cover"] = "./static/swine-fever.jpg";
          obj["title"] = "猪扒饭";
          obj["num"] += 1;
          obj["price"] -= 1;
        }
        i++;
        this.mockArr.push(obj);
      }
      this.list = this.mockArr;
    },
    handleTopChange(p_status) {
      this.topStatus = p_status;
    },
    handleBottomChange(p_status) {
      this.bottomStatus = p_status;
    },
    loadBottom() {
      // 一次下拉加载5条更多数据,使用定时器默认ajax加载
      this.loadData()
      this.number++;
      // allLoaded 设置为 true 时,表示数据已全部获取完毕不需要再出现上拉加载更多
      if (this.number === 3) {
        this.allLoaded = true;
      }
      this.$refs.loadmore.onBottomLoaded();
    },
    loadTop() {
      // 默认下拉刷新最新数据
      this.loadData("refresh");
      this.number = 0;
      this.allLoaded = false;
      this.$refs.loadmore.onTopLoaded();
    }
  }
};
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
/* 这里直接设置 1rem = 50px begin */
html {
  font-size: 50px;
}
/* 这里直接设置 1rem = 50px end */
html,
body {
  font-family: "微软雅黑";
  color: #333;
  background: #fff;
}
ul,
li {
  list-style: none;
}
/* 给要上拉的容器设置 begin */
.hello {
  height: 100vh;
  overflow-y: auto;
}
/* 给要上拉的容器设置 end */
.fl {
  float: left;
}
.fr {
  float: right;
}
.clearfix::before,
.clearfix::after {
  content: "";
  display: block;
  overflow: hidden;
  clear: both;
  visibility: hidden;
}
li {
  background: #fff;
}
.order-intr {
  position: relative;
  padding: 0.3rem 0.4rem;
  width: calc(100% - 0.6rem);
  margin: 0.4rem auto;
  border: 0.02rem solid #666;
  border-radius: 0.16rem;
}
.order-intr img {
  width: 3rem;
  height: 2.4rem;
}
.title {
  margin-left: 0.24rem;
  text-align: left;
}
.title h3 {
  font-size: 0.4rem;
}
.title p {
  font-size: 0.3rem;
}
.price {
  position: absolute;
  right: 0.3rem;
  bottom: 0.3rem;
  font-size: 0.5rem;
  color: #fe696b;
}
.mint-loadmore-top,
.mint-loadmore-bottom {
  font-size: 0.28rem;
}
/* 我是有底线的 begin */
.to-the-bottom {
  position: relative;
  color: #999999;
  font-size: 0.32rem;
  text-align: center;
  padding: 0.1rem 0;
  background: #f1eded;
}
.to-the-bottom::before,
.to-the-bottom::after {
  position: absolute;
  top: 50%;
  height: 0.02rem;
  width: 25%;
  margin-top: -0.01rem;
  background: #999;
  content: "";
}
.to-the-bottom::before {
  left: 10%;
}
.to-the-bottom::after {
  right: 10%;
}
/* 我是有底线的 end */
</style>

 

 

3、最后来一个单页代码(图片自己找,图片路径也可以自己改)

 

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>loadmore</title>
  <!-- 引入样式 -->
  <link rel="stylesheet" href="https://unpkg.com/mint-ui/lib/style.css">
  <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      /* 这里直接设置 1rem = 50px begin */
      html {
        font-size: 50px;
      }
      /* 这里直接设置 1rem = 50px end */
      html,
      body {
        font-family: "微软雅黑";
        color: #333;
        background: #fff;
      }
      ul,
      li {
        list-style: none;
      }
      /* 给要上拉的容器设置 begin */
      .data-list {
        height: 100vh;
        overflow-y: auto;
      }
      /* 给要上拉的容器设置 end */
      .fl {
        float: left;
      }
      .fr {
        float: right;
      }
      .clearfix::before,
      .clearfix::after {
        content: "";
        display: block;
        overflow: hidden;
        clear: both;
        visibility: hidden;
      }
      li {
        background: #fff;
      }
      .order-intr {
        position: relative;
        padding: 0.3rem 0.4rem;
        width: calc(100% - 0.6rem);
        margin: 0.4rem auto;
        border: 0.02rem solid #666;
        border-radius: 0.16rem;
      }
      .order-intr img {
        width: 3rem;
        height: 2.4rem;
      }
      .title {
        margin-left: 0.24rem;
        text-align: left;
      }
      .title h3 {
        font-size: 0.4rem;
      }
      .title p {
        font-size: 0.3rem;
      }
      .price {
        position: absolute;
        right: 0.3rem;
        bottom: 0.3rem;
        font-size: 0.5rem;
        color: #fe696b;
      }
      .mint-loadmore-top,
      .mint-loadmore-bottom {
        font-size: 0.28rem;
      }
      /* 我是有底线的 begin */
      .to-the-bottom {
        position: relative;
        color: #999999;
        font-size: 0.32rem;
        text-align: center;
        padding: 0.1rem 0;
        background: #f1eded;
      }
      .to-the-bottom::before,
      .to-the-bottom::after {
        position: absolute;
        top: 50%;
        height: 0.02rem;
        width: 25%;
        margin-top: -0.01rem;
        background: #999;
        content: "";
      }
      .to-the-bottom::before {
        left: 10%;
      }
      .to-the-bottom::after {
        right: 10%;
      }
      /* 我是有底线的 end */
      </style>
      
</head>

<body>
  <div id="app">
    <div class="data-list">
      <mt-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" @top-status-change="handleTopChange"
        @bottom-status-change="handleBottomChange" :autoFill="false" ref="loadmore">
        <ul>
          <li class="order-intr clearfix" v-for="(item, index) in list" :key="index">
            <img class="fl" :src="item.cover">
            <div class="title fl">
              <h3>{{item.title}}</h3>
              <p>数量:{{item.num}}</p>
            </div>
            <b class="fr price">¥{{item.price}}</b>
          </li>
        </ul>
        <div slot="top" class="mint-loadmore-top">
          <span v-show="topStatus !== 'loading'" :class="{ 'rotate': topStatus === 'drop' }">松手释放↓</span>
          <span v-show="topStatus === 'loading'">加载中</span>
        </div>
        <div slot="bottom" class="mint-loadmore-bottom">
          <span v-show="bottomStatus !== 'loading'" :class="{ 'rotate': bottomStatus === 'drop' }">松手释放↑</span>
          <span v-show="bottomStatus === 'loading'">加载中</span>
        </div>
        <p v-if="allLoaded" class="to-the-bottom">我是有底线的</p>
      </mt-loadmore>
    </div>
  </div>
  <!-- 先引入 Vue -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!-- 引入组件库 -->
  <script src="https://unpkg.com/mint-ui/lib/index.js"></script>
  <script>
    let vm = new Vue({
      el: '#app',
      data() {
        return {
          topStatus: "",
          bottomStatus: "",
          allLoaded: false,
          list: [],
          mockArr: [],
          number: 0
        };
      },
      created() {
        // ajax 模拟初始加载, 使用定时器默认ajax加载
        let timer = setTimeout(_ => {
          clearTimeout(timer);
          this.loadData('refresh');
        }, 200);
      },
      methods: {
        loadData(p_status) {
          // 第一次加载或者下拉刷新最新数据
          if (p_status === "refresh") {
            this.mockArr = [];
          }
          for (let i = 0; i < 5;) {
            let obj = {
              cover: "./static/chicken-wings.jpg",
              title: "奥尔良鸡中翅饭",
              num: 1,
              price: 14.88
            };
            obj["id"] = this.mockArr.length + 1;
            if (i % 2) {
              obj["cover"] = "./static/swine-fever.jpg";
              obj["title"] = "猪扒饭";
              obj["num"] += 1;
              obj["price"] -= 1;
            }
            i++;
            this.mockArr.push(obj);
          }
          this.list = this.mockArr;
        },
        handleTopChange(p_status) {
          this.topStatus = p_status;
        },
        handleBottomChange(p_status) {
          this.bottomStatus = p_status;
        },
        loadBottom() {
          // 一次下拉加载5条更多数据,使用定时器默认ajax加载
          this.loadData()
          this.number++;
          // allLoaded 设置为 true 时,表示数据已全部获取完毕不需要再出现上拉加载更多
          if (this.number === 3) {
            this.allLoaded = true;
          }
          this.$refs.loadmore.onBottomLoaded();
        },
        loadTop() {
          // 默认下拉刷新最新数据
          this.loadData("refresh");
          this.number = 0;
          this.allLoaded = false;
          this.$refs.loadmore.onTopLoaded();
        }
      }
    })
  </script>
</body>

</html>

 

这是 demo 百度云盘链接

链接: https://pan.baidu.com/s/1NSOQA8gU0rg20QqL2iPW8g

提取码: mhpp 

 

 

---------- 2019.08.14 补充 ----------

如果出现下面这个报错

Uncaught TypeError: Cannot read property 'onTopLoaded' of undefined

下面是官方对于refs的说明:

如何解决上面的报错,我这里推荐使用先判断在执行

this.$refs.loadmore && this.$refs.loadmore.onTopLoaded();

posted @ 2019-01-18 14:53  Tsingtree  阅读(1896)  评论(0编辑  收藏  举报