vue-infinite-loading2.0 中文文档

简介

这是一个使用在Vue.js中的无限滚动插件,它可以帮助你快速创建一个无限滚动列表。


特点

  • 移动端支持友好
  • 兼容任何一个可以滚动的元素
  • 有不同的旋转器可以作为加载动画
  • 支持加载后显示结果
  • 支持两个方向的无限加载

<p id="installation">安装</p>

<strong>注意:vue-infinite-loading2.0只能在Vue.js2.0中使用。如果你想在Vue.js1.0中使用,请安装vue-infinite-loading1.3版本</strong>

npm install vue-infinite-loading --save

导入方式

es6模块导入方式

import InfiniteLoading from 'vue-infinite-loading';
export default {
  components: {
    InfiniteLoading,
  },
};

CommonJS 模块导入方式

const InfiniteLoading = require('vue-infinite-loading');
export default {
  components: {
      InfiniteLoading,
  },
};

其他方式

<script src="/path/to/vue-infinite-loading/dist/vue-infinite-loading.js"></script>

vue-infinite-loading.js会注册一个全局变量VueInfiniteLoading,使用时需要这样:

 ...
 components: {
     VueInfiniteLoading:VueInfiniteLoading.default,
 }
...

开始

基础使用

在本例中,我们将创建一个基本的无限列表,有如下三个步骤:

  1. 在你的模板中,用v-for创建一个列表
  2. 将InfiniteLoading组件放在列表的底部;
  3. 将InfiniteLoading组件的ref属性设置为infiniteLoading,因为要用它来触发事件。
  4. 为InfiniteLoading组件创建并绑定一个加载回调函数。

Template

<template>
  <div>
    <p v-for="item in list">
    Line:
    <span v-text="item"></span>
    </p>
    <infinite-loading :on-infinite="onInfinite" ref="infiniteLoading">    </infinite-loading>
  </div>
</template>

Script

import InfiniteLoading from 'vue-infinite-loading';
export default {
  data() {
    return {
      list: []
    };
  },
  methods: {
    onInfinite() {
      setTimeout(() => {
        const temp = [];
        for (let i = this.list.length + 1; i <= this.list.length + 20; i++) {
          temp.push(i);
        }
        this.list = this.list.concat(temp);
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
      }, 1000);
    }
  },
  components: {
    InfiniteLoading
  }
};

在<strong>onInfinite</strong>函数中,每次我们都push 20 个数字到list数组中。我们使用<strong>setTimeout</strong>来模拟异步请求。最后,不要忘了触发一个<strong>$InfiniteLoading:loaded</strong>事件,它将告诉<strong>InfiniteLoading</strong>组件,数据已经下载成功。

现在,我们可以根据上面的代码,来显示效果。


<p id="hacker">例子:黑客新闻列表页面</p>

在这个例子中,我们将模仿一个黑客新闻列表页面,但是会用<strong>InfiniteLoading</strong>代替<strong>分页</strong>

在开始这个例子之前,我们需要准备以下内容:

  • 获取新闻列表的API,在本例中我们使用 HN Search API
  • 导入axios插件来请求数据

Template

<div class="hacker-news-list">
  <div class="hacker-news-header">
    <a target="_blank" href="http://www.ycombinator.com/">
      ![](https://news.ycombinator.com/y18.gif)
    </a>
    <span>Hacker News</span>
</div>
<div class="hacker-news-item" v-for="(item, key) in list">
  <span class="num" v-text="key + 1"></span>
  <p>
    <a target="_blank" :href="item.url" v-text="item.title"></a>
  </p>
  <p>
    <small>
      <span v-text="item.points"></span>
      points by
      <a target="_blank" :href="'https://news.ycombinator.com/user?id=' + item.author"
       v-text="item.author"></a>
        |
      <a target="_blank" :href="'https://news.ycombinator.com/item?id=' + item.objectID"
       v-text="item.num_comments + ' comments'"></a>
    </small>
  </p>
</div>
  <infinite-loading :on-infinite="onInfinite" ref="infiniteLoading">
  <span slot="no-more">
    There is no more Hacker News :(
  </span>
  </infinite-loading>
</div>

在模板中,我们为黑客新闻列表创建了一个header 和 一个list 。在这个例子中的<strong>InfiniteLoading</strong>组件,与上个例子中使用方式有些不同。我们基于<strong>slot</strong>自定义了当没有更多数据时的提示内容。

Script

import InfiniteLoading from 'vue-infinite-loading';
import axios from 'axios';
const api = 'http://hn.algolia.com/api/v1/search_by_date?tags=story';
export default {
  data() {
    return {
      list: []
    };
  },
  methods: {
    onInfinite() {
      axios.get(api, {
        params: {
          page: this.list.length / 20 + 1
        }
      }).then((res) => {
        if (res.data.hits.length) {
          this.list = this.list.concat(res.data.hits);
          this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
          if (this.list.length / 20 === 3) {
            this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
          }
        } else {
          this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
        }
      });
    }
  },
  components: {
    InfiniteLoading
  }
};

在<strong>onInfinite</strong>函数中,我们请求了一页的新闻,并且每次将它们推入到list数组中。如果我们请求了3页新闻,将触发 <strong>$InfiniteLoading:complete</strong>事件去告诉<strong>InfiniteLoading</strong>组件,现在已经没有更多数据可以加载了。它将显示我们自定义在模板中的,表示没有更多数据的提示内容。

Style

.hacker-news-list .hacker-news-item {
   margin: 10px 0;
   padding: 0 10px 0 32px;
   line-height: 16px;
   font-size: 14px;
}
.hacker-news-list .hacker-news-item .num {
  margin-top: 1px;
  margin-left: -32px;
  float: left;
  width: 32px;
  color: #888;
  text-align: right;
}
.hacker-news-list .hacker-news-item p {
  padding-left: 8px;
  margin: 0;
}
.hacker-news-list .hacker-news-item .num:after {
  content: ".";
}
.hacker-news-list .hacker-news-item p>a {
  color: #333;
  padding-right: 5px;
}
.hacker-news-list .hacker-news-item p a {
  text-decoration: none;
}
.hacker-news-list .hacker-news-item p small, .hacker-news-list .hacker-news-item p small a {
  color: #888;
}

<p id="use">与过滤器一块使用</p>

在上个例子的基础上,我们将在头部创建一个下拉选择作为过滤器,当我们改变过滤器,列表将会重新加载。

Template

<div class="hacker-news-list">
<div class="hacker-news-header">
  <a target="_blank" href="http://www.ycombinator.com/">
    ![](https://news.ycombinator.com/y18.gif)
  </a>
  <span>Hacker News</span>
  <select v-model="tag" @change="changeFilter()">
    <option value="story">Story</option>
    <option value="poll">Poll</option>
    <option value="show_hn">Show hn</option>
    <option value="ask_hn">Ask hn</option>
    <option value="front_page">Front page</option>
 </select>
</div>
<div class="hacker-news-item" v-for="(item, key) in list">
  <span class="num" v-text="key + 1"></span>
  <p>
    <a target="_blank" :href="item.url" v-text="item.title"></a>
  </p>
  <p>
    <small>
      <span v-text="item.points"></span>
      points by
      <a target="_blank" :href="'https://news.ycombinator.com/user?id=' + item.author"
         v-text="item.author"></a>
      |
      <a target="_blank" :href="'https://news.ycombinator.com/item?id=' + item.objectID"
         v-text="item.num_comments + ' comments'"></a>
    </small>
  </p>
</div>
<infinite-loading :on-infinite="onInfinite" ref="infiniteLoading">
  <span slot="no-more">
    There is no more Hacker News :(
  </span>
</infinite-loading>
</div>

Script

import InfiniteLoading from 'vue-infinite-loading';
import axios from 'axios';
const api = 'http://hn.algolia.com/api/v1/search_by_date';
export default {
  data() {
    return {
      list: [],
      tag: 'story'
    };
  },
  methods: {
    onInfinite() {
      axios.get(api, {
        params: {
          tags: this.tag,
          page: this.list.length / 20 + 1
        }
      }).then((res) => {
        if (res.data.hits.length) {
          this.list = this.list.concat(res.data.hits);
          this.$refs.infiniteLoading.$emit('$InfiniteLoading:loaded');
          if (this.list.length / 20 === 10) {
            this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
          }
        } else {
          this.$refs.infiniteLoading.$emit('$InfiniteLoading:complete');
        }
      });
    },
    changeFilter() {
      this.list = [];
      this.$nextTick(() => {
        this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
      });
    }
  },
  components: {
    InfiniteLoading
  }
};

在<strong>changeFilter</strong>函数中,我们清楚了列表并等待DOM更新,然后我们触发一个<strong>$InfiniteLoading:reset</strong>事件,目的是让<strong> InfiniteLoading </strong>组件回到最初状态,它将立刻请求新的数据。

Style

在上个例子基础上增加样式

.demo-inner {
  margin-left: 20px;
  width: 261px;
  height: 455px;
  border: 1px solid #ccc;
  overflow: auto;
}
.hacker-news-list .hacker-news-header {
    padding: 2px;
    line-height: 14px;
    background-color: #f60;
}
.hacker-news-list {
  min-height: 455px;
  background-color: #f6f6ef;
}
.hacker-news-list .hacker-news-header select {
    float: right;
    color: #fff;
    background-color: transparent;
    border: 1px solid #fff;
    outline: none;
}

<p id="server">服务端渲染</p>

服务端渲染(SSR)是<strong>Vue.js2.0</strong>的新特性,当你在你的SSR应用中使用这个组件,会得到类似这样的错误:

Error: window is not defined
ReferenceError: window is not defined
    at ...
    at ...
    at e.exports (...)
    at Object. (...)
    at p (...)
    at Object.e.exports.render.e (...)
    at p (...)
    at Object. (...)
    at p (...)
    at e.__esModule.default (...)

因为<strong>style-loader</strong>不支持在这个时候本地导出,详情点这里,所以我们需要下面的变通方案,为了你的SSR应用:

  1.  import InfiniteLoading from 'vue-infinite-loading/src/components/Infiniteloading.vue';
    

    代替

     import InfiniteLoading from 'vue-infinite-loading';
    
  2. <strong>npm install less less-loader --save-dev</strong> 如果你还没有安装它们。

然后你的SSR应用应该运行良好。如果不是,你可以加入这个issue去讨论。


<p id="properties">属性<p>

  • on-infinite
    这是一个回调函数,当滚动到距离滚动父元素底部特定距离的时候,会被调用。
    通常,在数据加载完成后,你应该在这个函数中发送<strong>$InfiniteLoading:loaded</strong>事件。

    - type           Function
    - reuqired       true
    
  • distance
    这是滚动的临界值。如果到滚动父元素的底部距离小于这个值,那么<strong>on-infinite</strong>回调函数就会被调用。

    - type         Number
    - required     false
    - default      100
    - unit         pixel
    
  • spinner
    通过这个属性,你可以选择一个你最喜爱旋转器作为加载动画。点击这里可以看到所有可用的旋转器。

    - type         String
    - required     false
    - default     'default'
    
  • ref
    正如你所知,这个属性是一个Vue.js的官方指令,用来获取子组件的实例。我们需要用它来得到<strong> InfiniteLoading </strong>组件的实例来发送事件。你可以用这种方式来得到实例:<strong>this.$refs[the value of ref attribute].</strong>

    - type     String
    - required     true
    
  • direction
    如果你设置这个属性为top,那么这个组件将在你滚到顶部的时候,调用on-infinite函数。
    <strong>警告:你必须在数据加载后,手动地将滚动父元素的scrollTop设置为正确的值,否则,该组件会一次又一次调用on-infinite函数。</strong>

    - type         String
    - default     'bottom'
    

<p id="event">事件</p>

<strong>InfiniteLoading </strong>组件将处理一下事件。如果你需要通过组件的实例来<strong>$emit</strong>,则可以通过<strong>ref</strong>属性来得到组件实例。

  • $InfiniteLoading:loaded
    通常,你需要在数据加载后发送这个事件,<strong> InfiniteLoading</strong>组件将隐藏加载动画,并且准备下一次触发。

  • $InfiniteLoading:complete
    如果<strong>InfiniteLoading</strong>组件就不会接收<strong>$InfiniteLoading:loaded</strong>,当你发送这个事件后,它将为用户显示一个没有结果的提示。如果<strong>InfiniteLoading</strong>组件接收过<strong>$InfiniteLoading:loaded</strong>,当你发送这个事件的时候,它会为用户显示一个没有更多内容的提示。你可以利用slot来自定义需要显示的内容。
    你的<strong>onInfinite</strong>函数可能像这个样子:

    onInfinite() {
        this.$http.get(url, (res) => {
        if (res.data) {
          this.list = this.list.concat(res.data);
          this.$refs[your ref attirbute's value].$emit('$InfiniteLoading:loaded');
        } else {
          this.$refs[your ref attirbute's value].$emit('$InfiniteLoading:complete');
        }
      });
    }
    
  • $InfiniteLoading:reset
    <strong>InfiniteLoading</strong>组件将会回到最初的状态,并且<strong>on-infinite</strong>函数将会立刻被调用。大部分情况下,如果你把这个组件同过滤器或制表符一起使用,这个事件还是有用的。

<p id="slots">插槽</p>

你可以利用<strong>slot</strong>自定义提示的内容,当然,如果你喜欢的话,也可以使用默认内容:

  <span slot="{{ slot name }}">
    {{ Your content }}
 </span>
  • no-results
    当<strong>InfiniteLoading</strong>组件接收到<strong>$InfiniteLoading:complete </strong>事件并且它没有接收过<strong>$InfiniteLoading:loaded</strong>事件时,这个内容会显示出来。

    - type       String
    - default     No results :(
    
  • no-more
    当<strong>InfiniteLoading</strong>组件接收到<strong>$InfiniteLoading:complete </strong>事件并且它已经接收过<strong>$InfiniteLoading:loaded</strong>事件时,这个内容会出现。

  • spinner
    如果,你不喜欢当前旋转器,你可以自定义自己的旋转器作为加载时的动画。

    - type         HTML
    - default     default spinner
    

<p id="spinners">旋转器</p>

你可以用<strong>spinner</strong>属性,选择你最喜爱的旋转器作为加载动画:

  <infinite-loading spinner="{{ spinner name }}"></infinite-loading>

点击这里可以查看几个可用的旋转器。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • 转载 :OpenDiggawesome-github-vue 是由OpenDigg整理并维护的Vue相关开源项目库...
    果汁密码阅读 23,083评论 8 124
  • 来源:github.com Vue.js开源项目速查表:https://www.ctolib.com/cheats...
    zhangtaiwei阅读 11,593评论 1 159
  • UI组件element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于...
    董董董董董董董董董大笨蛋阅读 8,499评论 6 123
  • 没想到果果这次参赛能得一等奖,而且还有五佰元奖金!真是意外的惊喜!所以,无论干什么,只要持之以恒,努力去做,就会有...
    阿盟果果阅读 223评论 0 0
  • 昨天早上,在公园里散步,见到好几块新辟的菜地,一个奶奶蹲在旁边望着地里新长的绿芽发呆。我也是闲来无事,就上去聊了几...
    苏晓懒阅读 401评论 2 1