33

在vue中实现下拉加载数据,瀑布流

说明

节约流量
提高用户体验

不至于每次把所有数据加载出来,出现用户等待时间较长

实现方式

需求:

当用户打开首页的时候显示8条数据,当用户滚动到屏幕可视区边缘的时候,然后触发一个函数,请求一个api加载新的数据,并且填充到之前的数据下面。

实现:

vue-infinite-scroll

vue插件:vue-infinite-scroll
github地址

安装

npm i vue-infinite-scroll -D

在main.js入口文件里面引入

使用CommonJS方式
// 注册全局
var infiniteScroll =  require('vue-infinite-scroll');
Vue.use(infiniteScroll)
 
//单独的组件里面使用
var infiniteScroll = require('vue-infinite-scroll');
new Vue({
  directives: {infiniteScroll}
})
使用 ES2015的方式
// 注册全局
import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll)
 
//单独的组件里面使用
import infiniteScroll from 'vue-infinite-scroll'
new Vue({
  directives: {infiniteScroll}
})

使用方式

Use v-infinite-scroll to enable the infinite scroll, and use infinite-scroll-* attributes to define its options.
使用v-infinite-scroll启用无限滚动,并使用无限滚动- *属性来定义它的选项。

The method appointed as the value of v-infinite-scroll will be executed when the bottom of the element reaches the bottom of the viewport.

当元素底部到达viewport底部时,将触发v-infinite-scroll值的方法。

<div v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
  ...
</div>
var count = 0;

new Vue({
  el: '#app',
  data: {
    data: [],
    busy: false
  },
  methods: {
    loadMore: function() {
      this.busy = true;

      setTimeout(() => {
        for (var i = 0, j = 10; i < j; i++) {
          this.data.push({ name: count++ });
        }
        this.busy = false;
      }, 1000);
    }
  }
});

选项

选项 描述
infinite-scroll-disabled 如果该属性的值为true,则将禁用无限滚动。
infinite-scroll-distance 数字(默认值= 0)——在执行v -infinite- scroll方法之前,元素底部和viewport底部之间的最小距离。
infinite-scroll-immediate-check 布尔值(默认值= true)表示该指令应该在绑定后立即检查。如果可能,内容不够高,不足以填满可滚动的容器。
infinite-scroll-listen-for-event 当事件在Vue实例中发出时,无限滚动将再次检查。
infinite-scroll-throttle-delay 下次检查和这次检查之间的间隔(默认值= 200)

后端实现:

需求分析:

接收参数:

每页有多少条 prePage
第几页(当前页) page
当我们第一次加载数据的时候加载8条
区分第一次和不是第一次加载

代码实现

在dom里面
<div class="accessory-list-wrap">
                    <div class="accessory-list col-4">
                        <ul>
                            <li v-for="(item,index) in goods" :key="index">
                                <div class="pic">
                                    <a href="#"><img v-lazy="'/static/img/' + item.productImage" alt=""></a>
                                </div>
                                <div class="main">
                                    <div class="name">{{item.productName}}</div>
                                    <div class="price">{{item.salePrice}}</div>
                                    <div class="btn-area">
                                        <a href="javascript:;" class="btn btn--m">加入购物车</a>
                                    </div>
                                </div>
                            </li>
                            <div v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
                            ...
                            </div>
                        </ul>
                    </div>
                </div>
vue 组件里面:
data(){
    return{
            busy: true,
        page:1,
        pageSize:8,
    }
},methods:{


 getGoodsList(flag){
                let sort = this.sortFlag ? 1 : -1;
                let param = {
                    sort:sort,
                    priceLevel:this.priceChecked,
                    page:this.page,
                    pageSize:this.pageSize
                }
                axios.get('/goods/list',{params:param}).then(res=>{
                    if(flag){
                        // 多次加载数据
                        this.goods = this.goods.concat(res.data.result);
                        if(res.data.result.length == 0){
                            this.busy = true;
                        }else{
                            this.busy = false;
                        }
                    }else{
                        // 第一次加载数据
                        this.goods = res.data.result;
                        // 当第一次加载数据完之后,把这个滚动到底部的函数触发打开
                        this.busy = false;
                    }
                })
            },
            loadMore: function() {
                this.busy = true;
                // 多次加载数据
                setTimeout(() => {
                    this.page ++;
                    this.getGoodsList(true);
                }, 1000);
            }
}
    let currentPage = parseInt(req.param('page')) > 0 ? parseInt(req.param('page')) : 1;
    let pageSize = parseInt(req.param('pageSize')) > 0 ? parseInt(req.param('pageSize')) : 8;
  // 要跳过多少条
    let skip = (currentPage - 1) * pageSize;

     let goodsModel = Goods.find(param);
    goodsModel.sort({ 'salePrice': sort }).skip(skip).limit(pageSize);

    goodsModel.exec({}, function(err, doc) {
        if (err) {
            res.json({ status: "1", msg: err.message })
        } else {
            res.json({ status: '0', msg: '', result: doc })
        }
    })

后续会优化


西树先森
7.1k 声望926 粉丝

从事开发多年,前端、后端(go、Python、php)、服务架构都有涉猎,经历过大公司、创业公司,擅长前端及公司技术选型。