vue-element(四) el-table滚动加载

说明

自用

一、自定义指令实现

参考:

vue element-ui table表格滚动加载

    1. template
<template>
  <el-table
    size="mini"
    :height="height"
    highlight-current-row
    v-loading="loading"
    v-loadmore="loadMore"
    :data="tableData"
  >
    <slot></slot>
    <template slot="append">
        <div class="no-more">
          我~是有底线的 (~ ̄▽ ̄)~
        </div>
    </template>
  </el-table>
</template>
    1. script
export default {
  name: 'WbTable',
  // 自定义指令
  //  vue 官方文档:https://cn.vuejs.org/v2/guide/custom-directive.html
  directives: {
    loadmore: {
      bind (el, binding) {
        const selectWrap = el.querySelector('.el-table__body-wrapper')
        selectWrap.addEventListener('scroll', function () {
          let sign = 100
          const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
          if (scrollDistance <= sign) {
            binding.value()
          }
        })
      }
    }
  },
  props: {
    // 服务端列表数据接口名称
    url: {
      type: String,
      required: true
    },
    // 服务端列表数据接口请求参数
    params: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      tableData: [],
      loading: false,
      total: 0
    }
  },
  created () {
    this.limit = this.params.limit ? this.params.limit : 8
    this.offset = this.params.offset ? this.params.offset : 0
    // 根据单元格最小高度计算表格高度
    this.height = this.limit * 45
    this.append(this.params)
  },
  methods: {
    append (params) {
      this.loading = true
      this.$http[this.url]({
        ...params,
        offset: this.offset,
        limit: this.limit
      })
        .then(result => {
          this.tableData = [
            ...this.tableData,
            ...result.data.rows
          ]
          console.log(this.tableData)
          this.total = result.data.total || 0
        })
        .finally(() => {
          this.loading = false
        })
    },
    reload () {
      // 刷新重置 offset 和表格
      this.params.offset = 0
      this.tableData = []

      // api动态加载完 开始重新请求数据
      this.$nextTick(() => {
        this.init(this.params)
      })
    },
    // 滚动事件
    loadMore () {
      const newOffset = this.offset + this.limit
      if (newOffset < this.total && !this.loading) {
        this.offset = newOffset
        this.append(this.params)
      }
    }
  }
}
  • 3.效果


二、与el-infinite-scroll 结合

有大佬已经实现了,查看:

element-ui 的 el-table 上使用无限滚动加载(与自带的 infinite-scroll 结合):https://blog.csdn.net/baidu_27769027/article/details/101924676
GitHub代码:https://github.com/yujinpan/el-table-infinite-scroll/blob/master/src/directives/table-infinite-scroll.js

三、 使用vue-infinite-loading实现滚动加载

参考:

官方文档(中文):https://peachscript.github.io/vue-infinite-loading/zh/
vue elmentui table 滚动加载:https://www.jianshu.com/p/48df3fd85dd6

1. 安装

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

npm install vue-infinite-loading --save
2.引入
import InfiniteLoading from 'vue-infinite-loading'
export default {
  name: 'WbTable',
  components: {InfiniteLoading}
}
3.完整使用
  • template
<template>
  <el-table
    size="mini"
    :height="height"
    highlight-current-row
    v-loading="loading"
    :data="tableData"
  >
    <slot></slot>
    <template slot="append">
      <!--
      @infinite: 滚动事件回调函数,当滚动到距离滚动父元素底部特定距离的时候,会被调用
      distance: 这是滚动的临界值。default: 100; 如果到滚动父元素的底部距离小于这个值,那么 loadMore 回调函数就会被调用。
      spinner: 通过这个属性,你可以选择一个你最喜爱旋转器作为加载动画
            'default' | 'bubbles' | 'circles' | 'spiral' | 'waveDots'
      direction: 如果你设置这个属性为top,那么这个组件将在你滚到顶部的时候,调用on-infinite函数
            'top' | 'bottom'
      forceUseInfiniteWrapper: (boolean | string) 强制指定滚动容器,使用CSS 选择器
      identifier: 识别号,改变时刷新
      -->
      <infinite-loading
        @infinite="loadMore"
        ref="infiniteLoading"
        :distance="100"
        spinner="bubbles"
        :identifier="infiniteId"
        force-use-infinite-wrapper=".el-table__body-wrapper">
        <!--   orce-use-infinite-wrapper 属性在存在多个 el-table 需要更详细的css选择器   -->
          <div class="no-more" slot="no-more">
            我~是有底线的 (~ ̄▽ ̄)~
          </div>
          <div class="no-more" slot="no-results">
            暂无结果 Ծ‸Ծ
          </div>
          <div class="no-more" slot="error">
            出错了 (╯‵□′)╯︵┻━┻
          </div>
      </infinite-loading>
    </template>
  </el-table>
</template>
  • script
import InfiniteLoading from 'vue-infinite-loading'
export default {
  name: 'WbTable',
  components: {InfiniteLoading},
  props: {
    // 服务端列表数据接口名称
    url: {
      type: String,
      required: true
    },
    // 服务端列表数据接口请求参数
    params: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      tableData: [],
      loading: false,
      total: 0,
      isOver: false,
      infiniteId: new Date()
    }
  },
  created () {
    this.limit = this.params.limit ? this.params.limit : 8
    this.offset = this.params.offset ? this.params.offset : 0
    // 根据单元格最小高度计算表格高度
    this.height = this.limit * 45
  },
  methods: {
    // 滚动事件
    async loadMore ($state) {
      this.loading = true
      if (!this.isOver) {
        await this.$http[this.url]({
          ...this.params,
          offset: this.offset,
          limit: this.limit
        })
          .then((result) => {
            this.tableData = [
              ...this.tableData,
              ...result.data.rows
            ]
            this.total = result.data.total || 0
            if (this.total <= this.tableData.length) {
              this.isOver = true
              $state.complete() // 全部加载完成
            } else {
              $state.loaded() // 单个数据加载完毕
              this.offset = this.offset + this.limit // 设置下一页
            }
            console.log(this.tableData, this.total)
          })
          .finally(() => {
            this.loading = false
          })
      }
    },
    reset () {
      this.offset = 0
      this.tableData = []
      this.infiniteId += 1
    }
  }
}

四、手动加载下一页

运用el-table的插槽append设置一个加载按钮,手动触发页面加载

  • template
<template>
  <el-table
    size="mini"
    highlight-current-row
    :height="tableHeight"
    :data="tableData"
    v-loading="loading"
    empty-text="暂无数据 Ծ‸Ծ"
  >
    <slot></slot>
    <template slot="append" v-if="total > limit">
      <div v-if="loading" class="table-append loading">
        <i class="fa fa-spinner fa-pulse fa-2x fa-fw"></i>
      </div>
      <div v-else-if="!isOver && !noMore && !isError" class="table-append next" @click="nextPage">
        <i class="fa fa-angle-double-down fa-2x fa-fw arrow"></i>
      </div>
      <div v-else class="table-append ending">
        <span v-show="isError">出错了 (╯‵□′)╯︵┻━┻</span>
        <span v-show="noMore">暂无数据 Ծ‸Ծ</span>
        <span v-show="isOver">我~是有底线的 (~ ̄▽ ̄)~</span>
      </div>
    </template>
  </el-table>
</template>
  • script
export default {
  name: 'WbTable',
  props: {
    // 服务端列表数据接口名称
    url: {
      type: String,
      required: true
    },
    // 服务端列表数据接口请求参数
    params: {
      type: Object,
      required: true
    },
    height: {
      type: [String, Number],
      default () {
        return 0
      }
    }
  },
  data () {
    return {
      tableData: [],
      loading: false,
      total: 0,
      isOver: false,
      isError: false,
      noMore: false
    }
  },
  created () {
    this.limit = this.params.limit ? this.params.limit : 8
    this.offset = this.params.offset ? this.params.offset : 0
    // 取设置的高度,否则按最小高度计算
    this.tableHeight = this.height ? this.height : this.limit * 45 + 80
    this.append(this.params)
  },
  methods: {
    // 列表新增
    async append (params) {
      this.loading = true
      this.$http[this.url]({
        ...params,
        offset: this.offset,
        limit: this.limit
      })
        .then(result => {
          if (!result.data) {
            this.noMore = true
            return
          }
          this.tableData = [
            ...this.tableData,
            ...result.data.rows
          ]
          this.total = result.data.total || 0
          console.log(this.tableData, this.total)
          //  判断是否需要加载下一页
          if (this.tableData.length >= this.total) {
            this.isOver = true
          }
        })
        // eslint-disable-next-line handle-callback-err
        .catch(error => {
          this.isError = true
        })
        .finally(() => {
          this.loading = false
        })
    },
    reset () {
      debugger
      this.offset = 0
      this.tableData = []
      this.total = 0
      this.isOver = false
      this.isError = false
      this.noMore = false
      // api动态加载完 开始重新请求数据
      this.$nextTick(() => {
        this.append(this.params)
      })
    },
    nextPage (event) {
      if (!this.isOver) {
        this.offset = this.offset + this.limit
        this.$nextTick(() => {
          this.append(this.params)
        })
      }
    }
  }
}
  • style
<style lang="scss" scoped>
.table-append {
  text-align: center;
  padding: 10px;
}
.ending {
  line-height: 24px;
}
.next {
  /*鼠标 手形状态*/
  cursor:pointer;
  &:focus,&:hover{
    color:#409EFF;
    border-color:#c6e2ff;
    background-color:#ecf5ff
  }
  &:active{
    color:#3a8ee6;
    border-color:#3a8ee6;
    outline:0
  }
  &::-moz-focus-inner{
    border:0
  }
}
.arrow {
/*  width: 20px;
  height: 20px;
  position: absolute;
  top: 0px;
  right: 50%;
  margin-left: -11px;
  border: 3px solid transparent;
  border-bottom: 3px solid #000;
  border-right: 3px solid #000;
  z-index: 99;
  opacity: .8;*/
  -webkit-transform: rotate(0deg);
  -webkit-animation: arrow 1.5s infinite ease-in-out;
}

@-webkit-keyframes arrow {
  0% {
    opacity:0;
    -webkit-transform:translate(0, -5px) rotate(0deg)
  }
  50% {
    opacity:1;
    -webkit-transform:translate(0, -0px) rotate(0deg)
  }
  100% {
    opacity:0;
    -webkit-transform:translate(0, 5px) rotate(0deg)
  }
}
</style>
<style lang="scss">
  .el-table__body-wrapper::-webkit-scrollbar{
    width: 1px;
  }
  .el-table__body-wrapper::-webkit-scrollbar-thumb{
    border-radius: 1px;
    height: 20px;
    background: rgba(58, 142, 230, 0.51);
  }
  .el-table__body-wrapper::-webkit-scrollbar-track{
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0);
    border-radius: 1px;
    background: rgba(0, 0, 0, 0);
  }
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 简说Vue (组件库) https://github.com/ElemeFE/element" 饿了么出品的VUE...
    Estrus丶阅读 1,225评论 0 1
  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,119评论 0 1
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    柴东啊阅读 15,803评论 2 140
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    王喂马_阅读 6,380评论 1 77
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    你猜_3214阅读 10,967评论 0 118