基于vxe-table的公共表格(包含大部分基础功能)

基于vxe-table的公共表格(包含大部分基础功能)_第1张图片
基于vxe-table的公共表格(包含大部分基础功能)_第2张图片
基于vxe-table的公共表格(包含大部分基础功能)_第3张图片

表格主组件

KTable.vue

HTML部分

<template>
  <div
    class="table-wrapper"
    v-loading="loading"
    element-loading-text="加载中..."
  >
    <vxe-table
      :ref="tableRef"
      :resizable="resizable"
      :class="[
        'my-table-scrollbar',
        tableRef,
        isNeedFirstLine ? 'hide-scroll-table' : '',
        border ? 'show-warp-border' : '',
        isShowColor ? 'is-show-color' : '',
        whetherToMerge || border ? 'set-table-border' : '',
        isShowTotal ? 'set-scroll-table' : '',
      ]"
      :data="tableData"
      :max-height="height ? height : minHeight"
      :row-config="{ isHover: true }"
      :sort-config="{ remote: true, trigger: 'cell', defaultSort: defaultSort }"
      :tooltip-config="{ showAll: false }"
      :border="border"
      :row-id="rowId"
      :show-footer="isShowTotal && tableData.length"
      :footer-span-method="isNeedTotalMerge && footerColspanMethod"
      :footer-method="footerMethod"
      :tree-config="
        dataStructure === '1'
          ? treeConfig1
          : treeConfig2.transform
          ? treeConfig2
          : false
      "
      :span-method="whetherToMerge && mergeRowMethod"
      header-row-class-name="vxe-table__header-row"
      :header-cell-style="headMerge"
      :cell-style="defaultCellStyle"
      :footer-cell-style="footerCellStyle"
      @scroll="handleScroll"
      @sort-change="val => sortChange(val, 'table')"
    >
      <vxe-table-column
        align="left"
        title="序号"
        width="80"
        :fixed="isFixed"
        v-if="showSerial && tableConfig.length"
      >
        <template v-slot="{ rowIndex }">
          <span>{{ rowIndex + (pageIndex - 1) * pageSize + 1 }}span>
        template>
      vxe-table-column>
      <k-table-column
        v-for="item in tableConfig"
        :key="item.prop"
        ref="KTableColumn"
        :options="item"
        :propsCode="propsCode"
        :resizeSearch="resizeSearch"
        :searchLoading="searchLoading"
        :sortConfigObj="sortConfigObj"
        :treeData="treeData"
        :treeDataProps="treeDataProps"
        @popoverOpen="popoverOpen"
        @filter-change="filterColumnChange"
        @sort-table-change="val => sortChange(val, 'custom')"
      >k-table-column>

      <slot>slot>

      <template #empty>
        <k-empty type="table">k-empty>
      template>
    vxe-table>
    <k-pagination
      v-if="tableData.length && isShowPagina"
      v-bind="$attrs"
      v-on="$listeners"
      :total="total"
      :page="page"
      :limit="limit"
    >k-pagination>
  div>
template>

JS部分

<script>
import KTableColumn from '../KTableColumn/index'
import KEmpty from '../KEmpty/index'
import KPagination from '@/components/KPagination'
import { numToFixed } from '@/util/common'
export default {
  name: 'KTable',

  components: {
    KTableColumn,
    KEmpty,
    KPagination,
  },
  props: {
    // 展示的code name
    propsCode: {
      type: Object,
      default: () => {
        return {
          prop: 'prop',
          label: 'label',
          children: 'children',
        }
      },
    },
    /**
     * 表格加载
     */
    loading: {
      type: Boolean,
      default: false,
    },
    /**
     * 单元格样式
     */
    isShowSecondColor: {
      type: Boolean,
      default: false,
    },
    /**
     * 如果首行需要颜色,但是表头传入为空,传入需要颜色的表头prop
     */
    tableHeaderProp: {
      type: String,
      default: '',
    },
    /**
     * 表格配置数据 Array
     *
     * 参数
     * | label | 表头文案 | String | 必传 |
     * | prop | 要渲染的内容字段key | String | 必传 |
     * | format | 要特殊处理的内容 | Function(row, index) |
     * | align |对齐方式,默认center | String | left/center/right | 默认center |
     * | width | 对应列的宽度 | string |
     * | min-width | 最小列宽度;会自动将剩余空间按比例分配 | Number/string | px, % | 默认120px |
     * | sort | 是否需要排序(如果filter和sort同时使用,filter会覆盖sort) | Boolean | 默认false |
     * | filter | 是否需要过滤(如果filter和sort同时使用,filter会覆盖sort) | Boolean | 默认false |
     * | showSerial | 是否需要序号 | Boolean | 默认true |
     * | children | 多级表头的数据集合 | Array |
     *
     * 方法
     * | @sort-change | 排序回调方法 | Function({ field, order }) |
     * | @filter-change | 过滤回调方法 | Function({ field, order, inputValue }) |
     */
    tableConfig: {
      type: Array,
      default: () => [],
    },

    /**
     * 表格数据
     */
    tableData: {
      type: Array,
      default: () => [],
    },

    /**
     * 合计行数据
     */
    totalRowData: {
      type: Object,
      default: () => {},
    },
    /**
     * 表格高度  592
     */
    height: {
      type: String || Number,
      default: '',
    },
    /**
     * 是否显示合计
     */
    isShowTotal: {
      type: Boolean,
      default: false,
    },
    /**
     * 合计是否需要合并
     */
    isNeedTotalMerge: {
      type: Boolean,
      default: false,
    },
    /**
     * 默认排序
     */
    defaultSort: {
      type: Object,
      default: () => {
        return {
          field: '',
          order: '',
        }
      },
    },
    /**
     * 合计是否需要放首行
     */
    isNeedFirstLine: {
      type: Boolean,
      default: false,
    },
    /**
     * 需要放首行的表格类名
     */
    tableClass: {
      type: String,
      default: '',
    },
    /**
     * 是否需要合并
     */
    whetherToMerge: {
      type: Boolean,
      default: false,
    },
    /**
     * 合计是否需要颜色
     */
    isShowColor: {
      type: Boolean,
      default: true,
    },
    /**
     * 需合并列表头prop
     */
    fields: {
      type: Array,
      default: () => [],
    },
    /**
     * 表头是否需要合并
     */
    isNeedHeaderMerage: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否显示分页
     */
    isShowPagina: {
      type: Boolean,
      default: false,
    },
    /**
     * @description: 最小高度
     */
    minHeight: {
      type: Number,
      default: 400,
    },

    /**
     * 是否显示序列
     */
    showSerial: {
      type: Boolean,
      default: false,
    },
    /**
     * 序号是否需要固定
     */
    isFixed: {
      type: String || Boolean,
      default: false,
    },
    /**
     * 是否要隐藏滚动条
     */
    isShowScroll: {
      type: Boolean,
      default: false,
    },
    /**
     * 筛选loading
     */
    searchLoading: {
      type: Boolean,
      default: false,
    },
    /**
     * 树形表格数据结构
     *  如果等于1则数据结构为:
     *   {
     *     name: 'Test1',
     *     children: [
     *       {
     *         name: 'Test1',
     *       }
     *     ]
     *   },
     *   如果等于2则数据结构为:
     *    {
     *       id: 10050,
     *       parentId: null,
     *       name: 'Test2',
     *     },
     *     {
     *       id: 24300,
     *       parentId: 10050,
     *       name: 'Test3',
     *     },
     *
     *  dataStructure = ‘2’ 时 treeConfig2必传
     */
    dataStructure: {
      type: String,
      default: '2',
    },
    /**
     * 树形表格配置属性1
     */
    treeConfig1: {
      type: Object,
      default: () => {
        return {
          /**
           * 树形表格子节点名称
           */
          children: 'children',
          iconOpen: 'iconfont icon-chevron-up',
          iconClose: 'iconfont icon-chevron-down',
        }
      },
    },
    /**
     * 树形表格配置属性2
     */
    treeConfig2: {
      type: Object,
      default: () => {
        return {
          /**
           * 是否开启树形表格
           */
          transform: false,
          /**
           * 树形表格每行唯一ID的key
           */
          rowField: 'id',
          /**
           * 树形表格父节点唯一ID
           */
          parentField: 'parentId',
          iconOpen: 'iconfont icon-chevron-up',
          iconClose: 'iconfont icon-chevron-down',
        }
      },
    },
    /**
     * 重置查询条件
     */
    resizeSearch: {
      type: Boolean,
      default: false,
    },
    // 查询条件中的树
    treeData: {
      type: Array,
      default: () => [],
    },
    // 筛选prop
    treeDataProps: {
      type: Object,
      default: () => {
        return {
          value: 'prop',
          label: 'label',
          children: 'children',
        }
      },
    },
    // 默认排序
    sortConfigObj: {
      type: Object,
      default: () => {
        return {
          code: '',
          orderType: '',
        }
      },
    },
    /**
     * rowId
     */
    rowId: {
      type: String,
      default: 'id',
    },
    /**
     * 是否支持表头拖拽
     */
    resizable: {
      type: Boolean,
      default: false,
    },
    // 选中的tab
    activeTabType: {
      type: String,
      default: '',
    },
    // 是否显示边框
    border: {
      type: Boolean || String,
      default: 'inner',
    },
    /**
     * @description: 总条目数
     */
    total: {
      required: false,
      type: Number,
    },
    /**
     * @description: 当前页数
     */
    page: {
      type: Number,
      default: 1,
    },
    /**
     * @description: 每页显示条目个数,支持 .sync 修饰符
     */
    limit: {
      type: Number,
      default: 20,
    },
  },

  data() {
    return {
      scrollLeft: 0,
      tableRef: '',
    }
  },
  created() {
    this.tableRef = `table-${this.guid2()}`
  },
  /**
   * 计算页数及条数
   */
  computed: {
    pageIndex() {
      return this.page
    },
    pageSize() {
      return this.limit
    },
  },
  methods: {
    /**
     * 弹框开启
     */
    popoverOpen(val) {
      this.$emit('popoverOpen', val)
    },
    /**
     * 表格筛选里面的排序
     * @param val
     */
    sortTableChange(val) {
      this.$emit('sort-table-change', val)
    },
    /**
     * 生成表格id
     * @returns {string}
     */
    guid2() {
      function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
      }

      return (
        S4() +
        S4() +
        '-' +
        S4() +
        '-' +
        S4() +
        '-' +
        S4() +
        '-' +
        S4() +
        S4() +
        S4()
      )
    },
    /**
     * 表格滚动条位置
     * @param ev
     */
    handleScroll(ev) {
      this.scrollLeft = ev.scrollLeft
    },
    /**
     * 当前滚动条的位置
     * @param val
     */
    tableSimulationFun(val) {
      this.scrollLeft = val.scrollLeft
      this.$refs[this.tableRef].scrollTo(val.scrollLeft, '')
    },
    /**
     * 排序回调
     */
    sortChange(column, type) {
      const { field, order } = column
      this.$emit('sort-change', {
        field,
        order,
        type,
      })
      if (type === 'custom') {
        this.$nextTick(() => {
          this.$refs[this.tableRef].clearSort()
        })
      }
    },
    /**
     * 自定义序号
     */
    seqMethod() {},
    /**
     * 过滤回调
     */
    filterColumnChange(val) {
      this.$emit('filter-change', val)
    },

    /**
     * 过滤条件
     */
    filterMethod({ option, row }) {
      let k = null
      for (k in row) {
        if (row[k] === option.data) {
          return true
        }
      }
      return false
    },
    /**
     * 合计
     */
    footerMethod({ columns }) {
      const methodArr = []
      columns.forEach((column, _columnIndex) => {
        if (this.isNeedTotalMerge) {
          if (_columnIndex === 0 || _columnIndex === 1) {
            methodArr.push('合计')
          } else if (
            this.totalRowData[column.field] === '' ||
            this.totalRowData[column.field] === null
          ) {
            methodArr.push('-')
          } else {
            if (this.tableConfig && this.tableConfig.length) {
              this.tableConfig.forEach(item => {
                if (item[this.treeDataProps.value] === column.field) {
                  if (item.type === 'NUMBER' || item.type === 'Number' || item.type === 'number') {
                    const data = numToFixed(
                      this.totalRowData[column.field],
                      item.digit,
                      item.division,
                      item.empty
                    )
                    if (item.percentage) {
                      data.toString().indexOf('%') !== -1 ? methodArr.push(data) : methodArr.push(`${data}%`)
                    } else {
                      methodArr.push(data)
                    }
                  } else {
                    if (item.percentage) {
                      this.totalRowData[column.field].toString().indexOf('%') !== -1 ? methodArr.push(this.totalRowData[column.field]) : methodArr.push(`${this.totalRowData[column.field]}%`)
                    } else {
                      methodArr.push(this.totalRowData[column.field])
                    }
                  }
                }
              })
            }
          }
        } else {
          if (_columnIndex === 0) {
            methodArr.push('合计')
          } else if (
            this.totalRowData[column.field] === '' ||
            this.totalRowData[column.field] === null
          ) {
            methodArr.push('-')
          } else {
            if (this.tableConfig && this.tableConfig.length) {
              this.tableConfig.forEach(item => {
                if (item[this.treeDataProps.value] === column.field) {
                  if (item.type === 'NUMBER' || item.type === 'Number' || item.type === 'number') {
                    const data = numToFixed(
                      this.totalRowData[column.field],
                      item.digit,
                      item.division,
                      item.empty
                    )
                    if (item.percentage) {
                      data.toString().indexOf('%') !== -1 ? methodArr.push(data) : methodArr.push(`${data}%`)
                    } else {
                      methodArr.push(data)
                    }
                  } else {
                    if (item.percentage) {
                      this.totalRowData[column.field].toString().indexOf('%') !== -1 ? methodArr.push(this.totalRowData[column.field]) : methodArr.push(`${this.totalRowData[column.field]}%`)
                    } else {
                      methodArr.push(this.totalRowData[column.field])
                    }
                  }
                }
              })
            }
          }
        }
      })
      return [methodArr]
    },
    /**
     * 合并单元格
     */
    mergeRowMethod({ row, _rowIndex, column, visibleData }) {
      if (this.whetherToMerge && !this.fields.length)
        return this.$message.warning('请输入需合并列的表头code')
      const cellValue = row[column.property]
      if (cellValue && this.fields.includes(column.property)) {
        const prevRow = visibleData[_rowIndex - 1]
        let nextRow = visibleData[_rowIndex + 1]
        if (prevRow && prevRow[column.property] === cellValue) {
          return {
            rowspan: 0,
            colspan: 0,
          }
        } else {
          let countRowspan = 1
          while (nextRow && nextRow[column.property] === cellValue) {
            nextRow = visibleData[++countRowspan + _rowIndex]
          }
          if (countRowspan > 1) {
            return {
              rowspan: countRowspan,
              colspan: 1,
            }
          }
        }
      }
    },
    /**
     * 合计行合并
     */
    footerColspanMethod({ $rowIndex, _columnIndex }) {
      if ($rowIndex === 0) {
        if (_columnIndex === 0) {
          return {
            rowspan: 1,
            colspan: 2,
          }
        } else if (_columnIndex === 1) {
          return {
            rowspan: 0,
            colspan: 0,
          }
        }
      }
    },
    /**
     * 表头合并
     */
    headMerge({ column, $rowIndex, columnIndex }) {
      if (this.isNeedHeaderMerage) {
        if ($rowIndex === 0) {
          if (columnIndex === 0) {
            this.$nextTick(() => {
              if (document.getElementsByClassName(column.id).length !== 0) {
                document
                  .getElementsByClassName(column.id)[0]
                  .setAttribute('colSpan', '2')
                return false
              }
            })
          } else if (columnIndex === 1) {
            return { display: 'none' }
          }
        }
      }
      return {
        // 表头参数
        backgroundColor: '#F3F8FD',
        fontSize: '14px',
        color: '#333333',
        lineHeight: '36px',
        fontWeight: 700,
        height: '36px',
        fontFamily: 'MicrosoftYaHei-Bold, Microsoft-YaHei',
        borderColor: '#E3E6EA',
        padding: '0',
      }
    },
    /**
     * 设置行样式
     */
    defaultCellStyle({ column }) {
      const tableClass = this.tableClass
        ? `.${this.tableClass}.set-first-color`
        : ''
      if (tableClass) {
        const setColor = document.querySelector(tableClass)
        const prop = this.tableConfig.length
          ? this.tableConfig[0].prop
          : this.tableHeaderProp
        if (setColor && column.property === prop) {
          return {
            fontWeight: '700',
            height: '36px',
            padding: '0',
            color: '#333333',
            borderColor: '#E3E6EA',
            backgroundColor: '#F3F8FD',
            fontFamily: 'Microsoft-YaHei',
            fontSize: '14px',
          }
        } else if (
          setColor &&
          this.isShowSecondColor &&
          column.property === this.tableConfig[1].prop
        ) {
          return {
            fontWeight: '700',
            height: '36px',
            padding: '0',
            color: '#333333',
            borderColor: '#E3E6EA',
            backgroundColor: '#F3F8FD',
            fontFamily: 'Microsoft-YaHei',
            fontSize: '14px',
          }
        }
      }
      return {
        height: '36px',
        padding: '0',
        color: '#333333',
        fontWeight: '400',
        fontFamily: 'Microsoft-YaHei',
        fontSize: '14px',
        margin: '0',
        borderColor: '#E3E6EA',
      }
    },
    /**
     * 设置合计行样式
     */
    footerCellStyle() {
      return {
        height: '36px',
        padding: '0',
        fontFamily: 'Microsoft-YaHei',
        color: '#333333',
        fontSize: '14px',
        margin: '0',
        borderColor: '#E3E6EA',
      }
    },
  },
  mounted() {
    if (this.isNeedFirstLine) {
      let table = document.querySelector(
        `.${this.tableClass} .vxe-table .vxe-table--main-wrapper`
      )
      let footer = document.querySelector(
        `.${this.tableClass} .vxe-table--footer-wrapper`
      )
      let body = document.querySelector(
        `.${this.tableClass} .vxe-table--body-wrapper`
      )
      table.removeChild(footer)
      table.insertBefore(footer, body)
    }
  },
}
</script>

CSS部分


引入组件部分

KTableColumn.vue

HTML部分

<template>
  
  <vxe-colgroup
    v-if="options[propsCode.children]"
    :key="options[propsCode.prop]"
    :align="options.align || 'center'"
    :field="options[propsCode.prop]"
    :fixed="options.freeze ? 'left' : ''"
    :min-width="options.minWidth || testHead(options[propsCode.label], 18)"
    :sortable="options.sort || false"
    :title="options[propsCode.label]"
    show-header-overflow
    show-overflow
  >
    <k-table-column
      v-for="item in options[propsCode.children]"
      :key="item[propsCode.prop]"
      :options="item"
      :propsCode="propsCode"
      :resizeSearch="resizeSearch"
      :searchLoading="searchLoading"
      :sortConfigObj="sortConfigObj"
      :accuracy="accuracy"
      :treeData="treeData"
      :treeDataProps="treeDataProps"
      @popoverOpen="popoverOpen"
      @filter-change="filterColumnChange"
      @sort-table-change="val => sortChange(val, 'custom')"
    />
  vxe-colgroup>
  

  <vxe-column
    v-else
    :tree-node="options.treeNode"
    :key="options[propsCode.prop]"
    :align="options.align || 'left'"
    :field="options[propsCode.prop]"
    :fixed="options.freeze ? 'left' : ''"
    :min-width="options.minWidth || testHead(options[propsCode.label], 18)"
    :sortable="options.sort === '' || options.sort === undefined || options.sort === true"
    :title="options[propsCode.label]"
    show-overflow
    show-footer-overflow
  >
    
    <template v-if="options.filter" #header>
      <KTableFiltering
        ref="KTableFiltering"
        :defaultProps="treeDataProps"
        :field="options[propsCode.prop]"
        :loading="searchLoading"
        :mainCode="treeDataProps.value"
        :mainLabel="treeDataProps.label"
        :resizeSearch="resizeSearch"
        :sortConfigObj="sortConfigObj"
        :title="options[propsCode.label]"
        :treeCheckData="treeCheckData"
        :treeData="treeData"
        @popoverOpen="popoverOpen"
        @filter-change="filterChangeFun"
        @sort-table-change="sortTableChange"
      >KTableFiltering>
    template>
    

    
    <template #default="{ row, rowIndex }">
      {{ formatterTableData(row, rowIndex) }}
    template>
    
  vxe-column>
template>

JS部分

<script>
import KTableFiltering from '../KTableFiltering/index'
import { testHead } from '@/util'
import { numToFixed } from '@/util/common'

export default {
  name: 'KTableColumn',

  components: {
    KTableFiltering,
  },

  props: {
    accuracy: {
      type: String,
      default: '',
    },
    fixedVal: {
      type: Boolean,
      default: true,
    },
    // 展示的code name
    propsCode: {
      type: Object,
      default: () => {
        return {
          prop: 'prop',
          label: 'label',
          children: 'children',
        }
      },
    },
    options: {
      type: Object,
      default: () => ({}),
    },
    // 查询条件中的树
    treeData: {
      type: Array,
      default: () => [],
    },
    // 筛选prop
    treeDataProps: {
      type: Object,
      default: () => {
        return {
          value: 'prop',
          label: 'label',
          children: 'children',
        }
      },
    },
    /**
     * 筛选loading
     */
    searchLoading: {
      type: Boolean,
      default: false,
    },
    /**
     * 重置查询条件
     */
    resizeSearch: {
      type: Boolean,
      default: false,
    },
    // 默认排序
    sortConfigObj: {
      type: Object,
      default: () => {
        return {
          code: '',
          orderType: '',
        }
      },
    },
  },

  data() {
    return {
      sortActive: 0, // 排序激活状态

      inputValue: '', // 搜索输入框的值

      filterData: {
        // 确定后暂存的值
        sortActive: 0,
        inputValue: '',
        treeCheckData: [],
      },

      defaultProps: {
        // 树列表配置
        children: 'children',
        label: 'label',
      },

      treeCheckData: [9], // 树选择的id
    }
  },
  methods: {
    /**
     * 自动撑开
     */
    testHead,
    /**
     * 千分位
     */
    numToFixed,
    /**
     * 子级过滤回调
     */
    filterChangeFun(val) {
      this.$emit('filter-change', val)
    },
    /**
     * 弹框开启
     */
    popoverOpen(val) {
      this.$emit('popoverOpen', val)
    },
    /**
     * 表格筛选里面的排序
     * @param val
     */
    sortTableChange(val) {
      this.$emit('sort-table-change', val)
    },
    /**
     * 表格数据处理
     */
    formatterTableData(row, rowIndex) {
      // 定义全局变量
      const rowData = row[this.options[this.propsCode.prop]]
      // 如果为空或者null、undefined 则返回 '-'
      if (rowData === null || rowData === '' || rowData === undefined) return '-'
      // 如果存在type字段并且type值为'NUMBER'/'Number'/'number' 则返回千分位及小数位处理后数据
      if (this.options.type === 'NUMBER' || this.options.type === 'Number' || this.options.type === 'number') {
        let data = ''
        data = numToFixed(rowData, this.options.digit, this.options.division, this.options.empty)
        // 如果存在type字段并且type值为'NUMBER'/'Number'/'number' 和需要添加百分号 percentage为true
        if (this.options.percentage) {
          if (data.toString().indexOf('%') !== -1) return data
          data = data && data !== '-' ? `${data}%` : '-'
        }
       return data
      }
      // 如果需要添加百分号 percentage为true
      if (this.options.percentage && rowData !== '-') {
        if (rowData.toString().indexOf('%') !== -1) return rowData
        return rowData + '%'
      }
      // 自定义数据格式化方式
      if (this.options.format) {
        return this.options.format(row, rowIndex)
      }
      return rowData
    },
}
</script>

CSS部分



KPagination.vue

分页组件HTML部分

<template>
  <div
    :class="{
      hidden: hidden,
      ['k_pagination_position_' + position]: true,
      'left-right': position === 'left-right',
      'fixed-pagination': isShowScroll,
    }"
    class="k_pagination pageBox"
    :style="{ width: isShowScroll ? scrollWidth : '' }"
  >
    <el-pagination
      :class="{
        'fixed-pagination-padding': isShowScroll,
        'visibility-hidden': isVisibility,
      }"
      :current-page.sync="currentPage"
      :page-size.sync="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :pager-count="pagerCount"
      :total="total"
      v-bind="$attrs"
      @size-change="handleSizeChange"
      :background="isBackGround"
      @current-change="handleCurrentChange"
    />
  div>
template>

JS部分

<script>

import _ from 'lodash'

export default {
  name: 'KPagination',
  props: {
    /**
     * 是否固定在底部
     */
    isShowScroll: {
      type: Boolean,
      default: false,
    },
    /**
     * 是否固定在底部-是否显示
     */
    isVisibility: {
      type: Boolean,
      default: false,
    },
    /**
     * @description: 总条目数
     * @param
     * @author: zou hua
     */
    total: {
      required: true,
      type: Number,
    },
    /**
     * @description: 当前页数
     * @param
     * @author: zou hua
     */
    page: {
      type: Number,
      default: 1,
    },
    /**
     * @description: 每页显示条目个数,支持 .sync 修饰符
     * @param
     * @author: zou hua
     */
    limit: {
      type: Number,
      default: 20,
    },
    /**
     * @description: 每页显示个数选择器的选项设置
     * @param
     * @author: zou hua
     */
    pageSizes: {
      type: Array,
      default() {
        return [10, 20, 30, 40, 50, 100, 200, 300, 500]
      },
    },
    /**
     * @description: 总页数,total 和 page-count 设置任意一个就可以达到显示页码的功能;如果要支持 page-sizes 的更改,则需要使用 total 属性,移动端页码按钮的数量端默认值5
     * @param
     * @author: zou hua
     */
    pagerCount: {
      type: Number,
      default: document.body.clientWidth < 992 ? 5 : 7,
    },
    /**
     * @description: 组件布局,子组件名用逗号分隔
     * @param
     * @author: zou hua
     */
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper',
    },
    autoScroll: {
      type: Boolean,
      default: true,
    },
    /**
     * @description: 是否显示隐藏
     * @param
     * @author: zou hua
     */
    hidden: {
      type: Boolean,
      default: false,
    },
    /**
     * @description: 分页显示位置
     * @param 'right' / 'left' / 'center' / 'space-around' / 'space-between' / 'space-evenly' / 'left-right'
     * @author: zou hua
     */
    position: {
      type: String,
      default: 'left-right',
    },
    /**
     * 分页是否有边框以及背景默认是有
     */
    isBackGround: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      scrollWidth: 0,
      scrollWidth1: 0,
    }
  },
  computed: {
    currentPage: {
      get() {
        return this.page
      },
      set(val) {
        this.$emit('update:page', val)
      },
    },
    pageSize: {
      get() {
        return this.limit
      },
      set(val) {
        this.$emit('update:limit', val)
      },
    },
  },
  watch: {
    total: {
      handler() {
        this.getWidthNext()
      },
    },
  },
  mounted() {
    window.addEventListener('resize', _.debounce(this.getWidthNext, 150))
  },
  updated() {
    this.getWidthNext()
  },
  // 销毁监听
  beforeDestroy() {
    window.removeEventListener('resize', this.getWidth)
  },
  methods: {
    handleSizeChange(val) {
      this.currentPage = 1
      this.$emit('pagination', { current: 1, size: val })
    },
    handleCurrentChange(val) {
      this.$emit('pagination', { current: val, size: this.pageSize })
    },
    /**
     * 获取宽度
     */
    getWidth() {
      const vxeTable = document.getElementsByClassName('content-text')
      let vxeScrollWidth = 0
      Array.prototype.forEach.call(vxeTable, function (element) {
        if (element && element.clientWidth !== 0) {
          vxeScrollWidth = element.clientWidth
        }
      })
      this.scrollWidth = vxeScrollWidth + 'px'
    },
    getWidthNext() {
      this.$nextTick(() => {
        this.$nextTick(() => {
          this.$nextTick(() => {
            this.getWidth()
          })
        })
      })
    },
  },
}
</script>

CSS部分


公共方法部分参考其他文章

你可能感兴趣的:(javascript,前端)