使用Mint-UI的Loadmore實現上拉加載更多和下拉刷新

最近用 mint-ui 實現了上拉加載更多下拉刷新,正好今天有空就把實現過程都給記錄下來,下面我準備來個小白教程。css

我這個利用vue單頁和普通頁面方式展現。html

一、首先用腳手架 vue-cli 搭建環境(這裏我百度找了一個算看到舒服的教程,僅供參考)vue

二、Mint-UI (這裏官網快速上手,能夠根據裏面的教程快速的添加 mint-ui  到項目中去,圖片和代碼看都有,推薦本身看圖手敲代碼)webpack

 

.babelrc文件git

 

{
  "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.jsgithub

// 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 文件夾)web

<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>

 

 

三、最後來一個單頁代碼(圖片本身找,圖片路徑也能夠本身改)ajax

 

<!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 百度雲盤連接vue-cli

連接: https://pan.baidu.com/s/1NSOQA8gU0rg20QqL2iPW8g babel

提取碼: mhpp 

 

 

---------- 2019.08.14 補充 ----------

若是出現下面這個報錯

Uncaught TypeError: Cannot read property 'onTopLoaded' of undefined

下面是官方對於refs的說明:

如何解決上面的報錯,我這裏推薦使用先判斷在執行

this.$refs.loadmore && this.$refs.loadmore.onTopLoaded();
相關文章
相關標籤/搜索