element-ui的table实现滚动加载,涵el-table组件封装一份

1. 如果你是直接用的 el-table 组件;下面为一个示例

重点就是 a d d R o l l L i s t e n e r addRollListener addRollListener 函数,想快点弄上去看效果的直接弄这个函数吧
如果不在mounted中则一定要this.$nextTick(() => this.addRollListener())

addRollListener(cb) {
  const dom = this.$refs.myTable.bodyWrapper
  dom.addEventListener('scroll', () => {
    const scrollTop = dom.scrollTop
    // 变量windowHeight是可视区的高度
    const windowHeight = dom.clientHeight || dom.clientHeight
    // 变量scrollHeight是滚动条的总高度
    const scrollHeight = dom.scrollHeight || dom.scrollHeight
    if (scrollTop + windowHeight + 1 > scrollHeight) cb && cb()
  })
}

示例代码

<template>
  <div class="element-table-scroll">
    <el-table
      ref="myTable"
      v-loading="loading"
      :data="tableData"
      :height="500"
      border
      element-loading-background="rgba(0, 0, 0, 0.8)"
      class="table-left color-table"
    >
      <el-table-column label="序号" type="index" align="center" width="56" />
      <el-table-column
        prop="name"
        label="名字"
        sortable
        align="center"
      />
    </el-table>
  </div>
</template>

<script>
const dataName = ['涨', '车', '轴', '走', '周', '凤', '胡', '晶', '京', '梅', '韦', '小', '字', '陈', '程',
  '测', '就', '当', '费', '飞', '矿', '况', '李', '刘', '成', '龙', '于', '巷', '港', '翔']
const serviceArr = []
// service为模仿 服务端返回数据;具体数据你找后台;
const service = (param) => {
  const { pageNow, pageSize } = param
  const createData = (arr) => {
    const random = (number) => (Math.floor(Math.random() * number)).toFixed(0)
    const nameFn = () => Array.from(new Array(random(3) < 2 ? 2 : 3), () => dataName[random(dataName.length)]).join('')
    const data = Array.from(new Array(pageSize), (x, i) => nameFn()).map(name => ({ name }))
    arr.push(...data)
  }
  createData(serviceArr)
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        data: serviceArr.slice(pageSize * (pageNow - 1), pageSize * pageNow)
      })
    }, 500)
  })
}
export default {
  data() {
    return {
      tableData: [],
      loading: false,
      pageNow: 1,
      pageSize: 20
    }
  },
  created() {
    this.getList()
    this.$nextTick(() => this.addRollListener(() => this.scrollCallback()))
  },
  methods: {
    // 这个是获取列表信息的地方
    getList() {
      this.loading = true
      const param = {
        pageNow: this.pageNow,
        pageSize: this.pageSize
      }
      service(param).then(({ data }) => {
        this.tableData.push(...data)
        // .....
      }).finally(() => {
        this.loading = false
      })
    },
    // 这里是你写回调函数的地方(触发滚动)
    scrollCallback() {
      // ...
      console.log('触发滚动加载')
      this.pageNow++
      this.getList()
    },
    addRollListener(cb) {
      const dom = this.$refs.myTable.bodyWrapper
      dom.addEventListener('scroll', () => {
        const scrollTop = dom.scrollTop
        // 变量windowHeight是可视区的高度
        const windowHeight = dom.clientHeight || dom.clientHeight
        // 变量scrollHeight是滚动条的总高度
        const scrollHeight = dom.scrollHeight || dom.scrollHeight
        if (scrollTop + windowHeight + 1 > scrollHeight) cb && cb()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.element-table-scroll {
  height: 600px;
  display: flex;
}
</style>

2. 如果你的table被封成了组件;

  1. 如果你把上面的看过了;只需要在 a d d R o l l L i s t e n e r addRollListener addRollListener 函数中更改dom值;其他不变
  2. children[0]这个你去找找这个dom吧。万一不对就去找找吧。
  3. 逻辑就是通过 ref 获取子节点信息,然后在里面找你的 el-table
const dom = this.$refs.myTable.$children[0].bodyWrapper

以下为组件模式的示例代码

<template>
  <div class="element-table-scroll">
    <LhTable
      ref="myTable"
      :height="600"
      :table-config="tableConfig"
      :c-table-info="tableInfo"
      :pageination="false"
    />
  </div>
</template>

<script>
const dataName = ['涨', '车', '轴', '走', '周', '凤', '胡', '晶', '京', '梅', '韦', '小', '字', '陈', '程', '测', '就', '当', '费', '飞', '矿', '况', '李', '刘', '成', '龙', '于', '巷', '港', '翔']
const serviceArr = []
// service为模仿 服务端返回数据;具体数据你找后台;
const service = (param) => {
  const { pageNow, pageSize } = param
  const createData = (arr) => {
    const random = (number) => Math.floor(Math.random() * number).toFixed(0)
    const nameFn = () =>
      Array.from(
        new Array(random(3) < 2 ? 2 : 3),
        () => dataName[random(dataName.length)]
      ).join('')
    const data = Array.from(new Array(pageSize), (x, i) => nameFn()).map(
      (name) => ({ name })
    )
    arr.push(...data)
  }
  createData(serviceArr)
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        data: serviceArr.slice(pageSize * (pageNow - 1), pageSize * pageNow)
      })
    }, 500)
  })
}
import LhTable from './component/Table.vue'
export default {
  components: {
    LhTable
  },
  data() {
    return {
      tableConfig: [
        {
          label: '序号',
          type: 'index',
          width: '60px'
        },
        {
          label: '调取成功数量',
          prop: 'name'
        },
        {
          label: '调取成功设备占比',
          // h 等同与 vue 的 h 函数或者说 createElement 方法;规则等同;
          render: (h, { row }) => h('span', {}, row.name)
        }
      ],
      tableInfo: {
        tableData: [],
        loading: false
      },
      pageNow: 1,
      pageSize: 20
    }
  },
  created() {
    this.getList()
    this.$nextTick(() => this.addRollListener(() => this.scrollCallback()))
  },
  methods: {
    // 这个是获取列表信息的地方
    getList() {
      this.tableInfo.loading = true
      const param = {
        pageNow: this.pageNow,
        pageSize: this.pageSize
      }
      service(param)
        .then(({ data }) => {
          this.tableInfo.tableData.push(...data)
          console.log(this.tableInfo.tableData)
          // .....
        })
        .finally(() => {
          this.tableInfo.loading = false
        })
    },
    // 这里是你写回调函数的地方(触发滚动)
    scrollCallback() {
      // ...
      console.log('触发滚动加载')
      this.pageNow++
      this.getList()
    },
    addRollListener(cb) {
      // 重点就是去找组件的子集
      const dom = this.$refs.myTable.$children[0].bodyWrapper
      console.log(dom)
      dom.addEventListener('scroll', () => {
        const scrollTop = dom.scrollTop
        // 变量windowHeight是可视区的高度
        const windowHeight = dom.clientHeight || dom.clientHeight
        // 变量scrollHeight是滚动条的总高度
        const scrollHeight = dom.scrollHeight || dom.scrollHeight
        if (scrollTop + windowHeight + 1 > scrollHeight) cb && cb()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.element-table-scroll {
  height: 600px;
  display: flex;
}
</style>

2.1 lh-table组件

scss不改样式,less则改为less,都没用直接删除style里面内容

<template>
  <div v-loading="loadings" class="lh-table">
    <el-table
      ref="table"
      border
      :class="['table-msg color-table ', className]"
      :stripe="stripe"
      :highlight-current-row="highlight"
      :size="size"
      :data="tableDataCheck"
      :max-height="height"
      :row-class-name="rowClassName"
      :style="{ height: pageination ? 'calc(100% - 60px)' : '100%' }"
      :span-method="spanMethod"
      @cell-dblclick="(param) => $emit('cell-dblclick', param)"
      @cell-click="(param) => $emit('cell-click', param)"
    >
      <el-table-column
        v-for="colConfig in tableConfig.filter(
          (item) => item.lhDisplay !== 'none'
        )"
        :key="colConfig['id']"
        v-bind="colConfig"
        align="center"
      >
        <template slot-scope="scope">
          <render
            v-if="colConfig.render"
            :key="colConfig['id']"
            :render="colConfig.render"
            :row="scope.row"
            :index="scope.$index"
            :column="colConfig"
          />
          <span v-else-if="colConfig.type === 'index'">{{
            scope.$index + 1
          }}</span>
          <span v-else>{{
            scope.row[colConfig && colConfig.prop] || "-"
          }}</span>
        </template>
      </el-table-column>
    </el-table>
    <!-- <LhPageination -->
    <el-pagination
      v-if="pageination"
      small
      background
      :page-size="pageSize"
      :page-sizes="pageSizes"
      :current-page="currentPage"
      :total="totalNum"
      @current-change="handleCurrentChange"
      @size-change="handleSizeChange"
    />
  </div>
</template>

<script>
// 只是把官网的这个组件源码拷贝下来 修改了一下里面的样式及布局;
// 使用这个 lh-table 这个组件 直接把LhPageination去掉然后用官网的就行了;
// import LhPageination from '@/components/anHui-new/lhPageination/index.js'

const pageination = {
  currentPage: 1,
  totalNum: 0,
  pageSize: 30,
  pageSizes: [10, 15, 20, 30, 50, 100]
}
const render = {
  functional: true,
  props: {
    row: Object,
    render: Function,
    index: Number,
    column: {
      type: Object,
      default: null
    }
  },
  render: (h, data) => {
    const params = {
      row: data.props.row,
      index: data.props.index
    }
    if (data.props.column) params.column = data.props.column
    return data.props.render(h, params)
  }
}
export default {
  name: 'LhTable',
  components: {
    // LhPageination,
    render
  },
  props: {
    // table配置信息
    tableConfig: {
      type: Array,
      default: () => [
        {
          label: '序号',
          type: 'index',
          width: '80px'
        },
        {
          label: '名字',
          prop: 'name'
        },
        {
          label: '公司名称',
          prop: 'cmyName'
        }
      ]
    },
    // table的一些信息
    cTableInfo: {
      type: Object,
      default: () => ({
        // table的数据源
        tableData: [],
        // 是否开启加载等待
        loading: false
      })
    },
    // 分页配置
    cPageinationInfo: {
      type: Object,
      default: () => pageination
    },
    // 高度设置 具体参考官网的
    height: {
      type: Number,
      default: 250
    },
    // 是否显示分页器
    pageination: {
      type: Boolean,
      default: true
    },
    // 官网的
    size: {
      type: String,
      default: 'small'
    },
    // 官网的:highlight-current-row;高亮行
    highlight: {
      type: Boolean,
      default: true
    },
    // 给el-table添加class
    className: {
      type: String,
      default: ''
    },
    // 斑马条
    stripe: {
      type: Boolean,
      default: true
    },
    // 行样式回调函数  (官网的)
    rowClassName: {
      type: Function,
      default: () => {}
    },
    // 单元格合并回调函数(官网的)
    spanMethod: {
      type: Function,
      default: () => {}
    }
  },
  // 如果只有一个表格直接 provide/inject 多个表格则组件传参方式
  inject: {
    pageinationInfo: {
      default: () => ({
        lh_spe_flag: true
      })
    },
    tableInfo: {
      default: () => ({
        lh_spe_flag: true
      })
    }
  },
  data() {
    const { currentPage, totalNum, pageSize, pageSizes } = this.pageinationInfo.lh_spe_flag
      ? this.cPageinationInfo : this.pageinationInfo || pageination
    return {
      // pageLayout: pageLayout || [
      //   ['total', 'sizes'],
      //   ['prev', 'pager', 'next', 'jumper']
      // ],
      currentPage, // 当前页数
      totalNum, // 数据总条数
      pageSize, // 每页数据的条数
      pageSizes // 选择每页的条数
    }
  },
  computed: {
    loadings() {
      return this.tableInfo.lh_spe_flag
        ? this.cTableInfo.loading || false
        : (this.tableInfo && this.tableInfo.loading) || false
    },
    tableDataCheck() {
      return this.tableInfo.lh_spe_flag
        ? this.cTableInfo.tableData
        : this.tableInfo.tableData
    }
  },
  watch: {
    height(val) {
      console.log(val, 'val')
    },
    'pageinationInfo.totalNum'(n) {
      this.totalNum = n
    },
    'pageinationInfo.currentPage'(n) {
      this.currentPage = n
    }
  },
  methods: {
    handleCurrentChange(v) {
      console.log(1, v)
      this.$emit('current-change', v)
    },
    handleSizeChange(v) {
      this.$emit('size-change', v)
    }
  }
}
</script>

<style lang="scss" scoped>
.lh-table {
  position: relative;
  width: 100%;
  height: 100%;
  .table-msg {
    position: absolute;
  }
  .el-pagination {
    position: absolute;
    bottom: 0;
  }
  /deep/.el-table__body-wrapper {
    height: 100% !important;
    .el-table__empty-block {
      min-height: 10px !important;
    }
  }
}
</style>

效果图

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值