vue-infinite-loading2.0 中文文档

作者: 打铁大师 | 来源:发表于2017-02-14 13:12 被阅读11358次

    简介

    这是一个使用在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>
    

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

    相关文章

      网友评论

      • lrt97:为什么我写的在一些人的浏览器和电脑上无法触发 onInfinite 事件,导致未发送请求。本人iphone、电脑 chrome,ie 均成功。。。但本人一加3T自带浏览器失败,其它浏览器正常。。。
      • yuppy:为什么分页没办法按滚动下拉到底部在加载。我实现完一进页面就按分页全部加载出来了。
      • b0cf792a9f33:我想问下那个提示自定义内容是怎么修改的
        打铁大师:@pc_21 学习Java,朝着全栈方向发展。已经在公司开始写后端了。
        b0cf792a9f33:@no_shower 哥们在研究啥了,可以给小辈说说前端注重哪方面的学习吗
        打铁大师:@pc_21 很久没搞了,都忘了,帅哥
      • 空山谧语:你好,我在调用spinner其他样式时候,按照调用
        <infinite-loading spinner="{{ spinner name }}"></infinite-loading>,
        但vue会直接报错,我自己的写法是
        <infinite-loading spinner="{{ circles }}" :on-infinite="onInfinite" ref="infiniteLoading" :class="{showLoad:tip}"></infinite-loading>
        网页报错提示源码如下:
        - spinner="{{ circles }}": Interpolation inside attributes has been removed. Use v-bind or the colon shorthand instead. For example, instead of <div id="{{ val }}">, use <div :id="val">.

        报错里提示的是尖括号里不能有{{ }},如果这样不行的话,我很疑惑,试过多次写法一直报错,想问问作者你是如何操作的的呢?谢谢
        高明楼:@pc_21 :spinner="circles"
        spinner="circles"
        b0cf792a9f33:@no_shower :spinner="circles",报错circles is not defined
        打铁大师:@空山谧语 根据错误信息,你试下 :spinner="circles"
      • 62a92b45a99e:你好,感谢分享哟~然后我想请教一个问题,我实现了效果,可每一次上拉刷新的时候,会执行两次...也就是会获取两组数据....期待解答^_^
        北斗玉衡_e8b3:我也是,页面刷新请求了两次数据
        default_098c:我的也是,请问你找到解决方法了吗?
        3cd8859572e5:我也是

      本文标题:vue-infinite-loading2.0 中文文档

      本文链接:https://www.haomeiwen.com/subject/egutwttx.html