#在vue中实现下拉加载数据，瀑布流
## 说明

>节约流量
提高用户体验
不至于每次把所有数据加载出来，出现用户等待时间较长

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

### 实现：
vue-infinite-scroll

vue插件:[vue-infinite-scroll](https://www.npmjs.com/package/vue-infinite-scroll)
[github地址](https://github.com/ElemeFE/vue-infinite-scroll/)

### 安装
```
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值的方法。

```HTML
<div v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
  ...
</div>
```

```JavaScript
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);
            }
}

注意：

     setPriceFilter(index){
                this.priceChecked = index;
                this.page = 1; //设置了分页后在这每次筛选价格重置为第一页
                this.getGoodsList();
            },

```

#### this.busy的逻辑分析
项目打开的时候 默认关闭触发，就是当开浏览器的时候，不加载loadmore，

当执行完第一次加载数据把这个this.busy = false,打开触发。

当滚动到底部的时候，触发到loadmore函数，
先让this.busy = true,关闭触发loadmore

然后调用this.getGoodsList函数

如果数据没有加载完
this.busy = false 继续打开触发

如果所有数据加载完成
this.budy = true




```express代码实现
    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 })
        }
    })
```

## 后续会优化