1.Vant的介绍

​ Vant 是有赞开源的一套基于 Vue 2.0 的 Mobile 组件库。通过 Vant,可以快速搭建出风格统一的页面,提升开发效率。目前已有近 50 个组件,这些组件被广泛使用于有赞的各个移动端业务中。 Vant 旨在更快、更简单地开发基于 Vue 的美观易用的移动站点

2.下拉刷新和上拉加载的实现

(1)通过 npm 安装

1
npm i vant -S

3.在babel.config.js中配置

1
2
安装插件:
npm i babel-plugin-import -D
1
2
3
4
5
6
7
8
9
10
11
添加配置:
在 babel.config.js 中配置
module.exports = {
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant']
]
};

4.在main.js中引入样式表

1
import 'vant/lib/index.css'

5.在组件简单使用

1
2
3
4
5
6
7
8
9
<template>
<div class="contain">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<van-cell v-for="item in list" :key="item" :title="item" />
</van-list>
</van-pull-refresh>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<script>
import Vue from "vue";
import { List, Cell, PullRefresh } from "vant";
import { Toast } from "vant";
Vue.use(List);
Vue.use(Cell);
Vue.use(PullRefresh);

export default {
data: function() {
return {
list: [],
loading: false,
finished: false,
isLoading: false
};
},
methods: {
//返回
returnbtn() {
this.$router.go(-1);
},
// 上拉加载
onLoad() {
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
setTimeout(() => {
for (let i = 0; i < 20; i++) {
this.list.push(this.list.length + 1);
}
// 加载状态结束
this.loading = false;
// 数据全部加载完成
if (this.list.length >= 140) {
this.finished = true;
}
}, 1000);
},
// 下拉刷新
onRefresh() {
setTimeout(() => {
Toast("刷新成功");
this.isLoading = false;
this.list = [];
this.finished = false;
for (let i = 0; i < 20; i++) {
this.list.push(this.list.length + 1);
}
}, 1000);
}
}
};
</script>

6.在实际项目中的使用

<template>
  <div class="contain">
    <div class="backimg">
      <i class="iconfont icon-zuojiantou" @click="returnbtn()" />
      <div class="backimg-wenzi">评论</div>
    </div>
    <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
      <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
        <div class="hotcomments">
          <h4>最新评论------{{total}}</h4>
          <div class="hotcom" v-for="(item,index) in commentsLists" :key="index">
            <div class="hotcomimg">
              <img v-lazy="item.user.avatarUrl" alt />
              <div class="nickname">
                {{item.user.nickname}}
                <br />
                {{item.time | dateFormat('HH:mm')}}
              </div>
              <div class="lickedcount">
                {{item.likedCount}}
                <i class="iconfont icon-dianzan" />
              </div>
            </div>
            <div class="content">{{item.content}}</div>
          </div>
        </div>
      </van-list>
    </van-pull-refresh>
  </div>
</template>

<script>
import Vue from "vue";
import { List, Cell, PullRefresh } from "vant";
import { Toast } from "vant";
Vue.use(List);
Vue.use(Cell);
Vue.use(PullRefresh);

import myaxios, {
  getCommentList,
  postComment,
  isPassword
} from "@/tools/myaxios.js";
import { mapGetters } from "vuex";

export default {
  data: function() {
    return {
      list: [],
      loading: false,
      finished: false,
      isLoading: false,

      hotCommentsLists: [],
      commentsLists: [],
      total: 0, //总共的数据条数
      text: "",
      page: 1, //请求第几页
      pageSize: 10, //每页请求的数量
      total: 0 //总共的数据条数
    };
  },
  async created() {
    //创建组件时,加载第1页数据
    this.getList();
  },
  methods: {
    //返回
    returnbtn() {
      this.$router.go(-1);
    },
    // 上拉加载
    onLoad() {
      setTimeout(() => {
        this.page++;
        this.getList();
      }, 1000);
    },
    // 下拉刷新
    onRefresh() {
      setTimeout(() => {
        Toast("刷新成功");
        this.isLoading = false;
        this.commentsLists = [];
        this.finished = false;
        for (let i = 0; i < 20; i++) {
          this.list.push(this.commentsLists.length + 1);
        }
      }, 1000);
    },
    async getList() {
      console.log(this.$route.query.id)
      let { data } = await myaxios(
        "GET",
        getCommentList + this.$route.query.id,
        {
          offset: this.page,
          limit: this.pageSize
        }
      );
      this.total = data.total;
      this.loading = false;
      // 返回当前页面的列表
      let rows = data.comments;
      if (rows == null || rows.length === 0) {
        // 加载结束
        this.finished = true;
        return;
      }
      // 将新数据与老数据进行合并
      this.commentsLists = this.commentsLists.concat(rows);
      //如果列表数据条数>=总条数,不再触发滚动加载
      if (this.commentsLists.length >= this.total) {
        this.finished = true;
      }
    }
  }
};
</script>

<style lang="less" scoped>
.contain {
  //  返回
  .backimg {
    height: 40px;
    line-height: 40px;
    color: #fff;
    .backimg-wenzi {
      color: #fff;
      height: 40px;
      line-height: 40px;
    }
    .icon-zuojiantou {
      font-size: 24px;
      float: left;
    }
  }
  // 评论内容
  .hotcomments {
    h4 {
      color: #fff;
    }
    .hotcom {
      margin: 20px;
      color: #fff;
      .content {
        width: 260px;
        margin: 0 auto;
        //   height: 30px;
      }
      .hotcomimg {
        height: 40px;
        // border: 1px solid;
        img {
          float: left;
          width: 40px;
          height: 40px;
          border-radius: 50%;
        }
        .nickname {
          float: left;
          margin-left: 10px;
        }
        .lickedcount {
          float: right;
        }
      }
    }
  }
}

.postcomment {
  z-index: 1000;
  position: fixed;
  width: 100%;
  bottom: 0px;
  height: 50px;
  background-color: #fff;
}
// 图片懒加载
img[lazy="loading"] {
  background: url("../../assets/images/smallant.jpg");
  background-size: 40px;
}
</style>