美文网首页
滚动加载的列表

滚动加载的列表

作者: Geeker工作坊 | 来源:发表于2020-03-06 00:50 被阅读0次

    开始之前

    今儿的项目又遇见一个不按套路出牌的设计:一个列表页,设计图上是不分页查询,后台给的接口是分页查询。跟产品说加个分页,产品说用户就不想要分页(任性呀!)。可这么多数据一次性返回肯定是不行的,接口响应时间太长了。现在的爸爸们真的越来越有(难)品(伺)味(候)了。为了解决这个问题,决定把移动端常见的滚动加载放进来。

    代码开撸

    关于滚动加载的原理简单来讲就是我们设置一个高度固定的列表,当数据超过列表的高度,我们将产生出的滚动条拖拉到底部,到底部的时刻我们触发一次数据请求,把请求的数据添加数据列表中,触发页面重渲染就可以完成。没有想象中那么复杂。项目是基于Vue 和 ElementUI 做的,翻看 el-table 的时候发现一个属性,正好是用于实现该项功能的。

    看说明,如果需要对表格内容进行无限滚动的操作,就用这个。那就是我们用 el-tablev-infinite-scroll就可实现这个内容。但是直接用,还是稍微会有一点麻烦,所以在这里推荐使用在 github发现的一个指令el-table-infinite-scroll 直接实现对 el-table的滚动加载。

    此指令依赖于 element-ui@2.12.0,使用前请熟悉:

    安装

    npm install --save el-table-infinite-scroll
    

    全局引入

    import Vue from 'vue';
    import elTableInfiniteScroll from 'el-table-infinite-scroll';
    
    Vue.use(elTableInfiniteScroll);
    

    局部引入

    <script>
    import elTableInfiniteScroll from 'el-table-infinite-scroll';
    export default {
      directives: {
        'el-table-infinite-scroll': elTableInfiniteScroll
      }
    }
    </script>
    

    组件中使用

    <template>
      <el-table
        border
        height="400px"
        v-el-table-infinite-scroll="load"
        :data="tableData"
      >
        <el-table-column prop="date" label="日期" width="180"> </el-table-column>
        <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
        <el-table-column prop="address" label="地址"> </el-table-column>
      </el-table>
    </template>
    
    <script>
    import elTableInfiniteScroll from 'el-table-infinite-scroll';
    
    const exampleData = new Array(10).fill({
      date: '2016-05-02',
      name: '王小虎',
      address: '上海市普陀区金沙江路 1518 弄'
    });
    
    export default {
      directives: {
        'el-table-infinite-scroll': elTableInfiniteScroll
      },
      data() {
        return {
          tableData: exampleData
        };
      },
      methods: {
        load() {
          this.$message.success('加载下一页');
          this.tableData = this.tableData.concat(exampleData);
        }
      }
    };
    </script>
    
    <style scoped>
    .el-table {
      width: 100%;
    }
    </style>
    

    配置选项

    参考 element-ui 官网 https://element.eleme.cn/#/zh-CN/component/infiniteScroll#attributes

    用户体验改进

    我们把上面的代码实现一遍,会看到我们很轻松的就实现了我们想要的滚动列表加载的效果。上面的代码中我们看到当我们一进入页面就会执行一遍load方法。但是想如果我们数据初始化的时候数据量很小,没有必要进行翻页查询,举个极端的例子比如我们只有一条数据,那我们这次的请求就是无效请求,是一种浪费用户时间,加重服务器负担的行为 ,是不可取的,所以我们需要有一个判断,判断数据是否需要在进来页面就执行load方法。

    另外,对于后端接口的请求往往都是异步请求,返回数据是需要时间的,如果我们等待后台服务器返回数据这段时间内,反复触发了这个滚动加载的事件,特别是用户网络慢或者服务器负载大延长了服务器响应时间的时候,用户无聊的滚动着滚轮,大量的事件就会形成一个队列,依次向服务器发起请求,一个恶性的循环就形成了😨。另外测试人员对于这个问题也会测试的,他们就是拼命滑滚轮,玩死你(测试的同事看到了不要打我😷)。对于这个问题,我们同样需要设置一个条件,在请求后台数据的时候,我们不能进行数据请求的操作,另外为了交互的友好性,我们要提示用户数据正在加载中,请他们不要着急。

    再就是如果当前我们请求的数据总量已经达到了后台数据量的总数,我们同样不能再触发后台的数据请求,然后给用户一个友好的提示,告诉他们数据已经加载完了,就不要拼命玩滚轮了。

    综上我们需要改进的地方有三个:

    1. 判断页面初始化时是否要执行load方法

    2. 等待响应期间不能进行数据请求,并给出加载中的友好性提示

    3. 数据加载完成,禁止数据加载,并给出加载完成的友好性提示

    el-table-infinite-scroll 这个指令的属性同饿了么 InfiniteScroll 无限滚动,饿了么这个指令中 infinite-scroll-disabled:禁止滚动加载,infinite-scroll-immediate:是否立即执行加载,来充满容器,正好对应我们这三个改进的地方。


    指令我是全局配置,我把改进的代码线全部放到这里:

    <template>
        <el-row :gutter="20">
            <el-col :span="8">滚动的列表</el-col>
            <el-col :span="15">
                <el-table
                        border
                        height="100%"
                        v-el-table-infinite-scroll="load"
                        infinite-scroll-immediate="first"
                        infinite-scroll-disabled="disabled"
                        :data="tableData"
                >
                    <el-table-column prop="date" label="日期" width="180"> </el-table-column>
                    <el-table-column prop="name" label="姓名" width="180"> </el-table-column>
                    <el-table-column prop="address" label="地址"> </el-table-column>
                    <div slot="append" style="text-align: center">
                        <span v-if="loading" class="prompt">--- 加载中 ---</span>
                        <span v-if="noMore" class="prompt">--- 没有更多了 ---</span>
                    </div>
                </el-table>
            </el-col>
        </el-row>
    </template>
    
    <script>
        const exampleData = new Array(10).fill({
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
        });
        export default {
            name: "Table",
            data() {
                return {
                    loading:false,
                    dataCount:10,
                    tableData: []
                };
            },
            computed:{
                first(){
                    return this.dataCount > 10
                },
                noMore(){
                    return this.tableData.length >= this.dataCount
                },
                disabled(){
                    return this.loading || this.noMore
                }
            },
            methods: {
                load() {
                    this.$message.success('加载下一页');
                    this.loading = true;
                    setTimeout(()=>{
                        this.tableData = this.tableData.concat(exampleData);
                        this.loading = false;
                    },2000);
                }
            },
            mounted() {
                this.dataCount = 10;
                this.tableData = [...exampleData];
            }
        }
    </script>
    
    <style scoped>
        .prompt{
            display: inline-block;color: #d3dce6;margin: 10px
        }
    </style>
    
    

    这里根据 el-table-infinite-scroll 要求,给table加了height属性并设置为100%,让高度自适应。我们假设每次请求后台只返回10条数据,而10条数据无法充满容器。所以设置计算属性first,判断数据总量是否小于10,小于10时进入页面就不执行load方法,由于数据无法充满容器,其实这个指令相当于无效,列表就是正常的展示。通过 noMore 和 loading 控制 el-table 插槽中提示信息的显示。然后通过disabled计算属性通过loading || noMore来控制是否允许滚动加载,也就是这两个值要有一个是true就不让其滚动加载。好了一个滚动的列表就完成了。测试的时候可以通过改动dataCount值来看效果。

    写在最后

    眼看一个周又要过去,这是冠状疫情之后在北京禁足的第四个周。很想念上班的时光,今天看到集团公众号刊登的武汉同事的一句话:“好久没有一起为一个需求和方案跟工作中的小伙伴当面‘吵架’了”。然后晚上跟我的back-end partner煲了一个小时的电话粥。希望疫情快点过去,大家喜乐安康,平安复工!最后附上这个指令的具体方式,希望能和大家在前端道路的一起进步。

    el-table-infinite-scroll 实现原理

    相关文章

      网友评论

          本文标题:滚动加载的列表

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