yeatszhang
12/1/2017 - 2:38 AM

iView Vue 分页表格

基于iView 支持异步以及同步模式。

/**
 * pageProps.pageSize  pageProps.current 为必填项
 * 可以通过调用实例方法在外层控制组件
 */

export default {
  props: {
    tableProps: {
      type: Object,
      default: () => {
      }
    },
    pageProps: {
      type: Object,
      default: () => {
        return {pageSize: 10, current: 1}
      }
    },
    /**
     * 如果是Function则必须返回Promise对象,表示表格数据从后端异步获取
     * 若果为数组则是整个表格的全部数据,在前端处理分页排序
     */
    tableData: {
      type: [Function, Array],
      required: true
    }
  },
  data () {
    return {
      sortFuncMap: {},
      current: this.pageProps.current || 1,
      data: [],
      total: 0,
      pageSize: this.pageProps.pageSize || 10,
      orderKey: '',
      order: 'normal',
      loading: false,
      // 移除columns sortMethods 之后
      processedTableProps: {}
    }
  },
  computed: {
    isAsync () {
      return typeof this.tableData === 'function'
    },
    sortable () {
      return this.orderKey && this.order && this.order !== 'normal'
    },
    _tableProps () {
      return Object.assign({}, this.processedTableProps, {
        data: this.data,
        stripe: true,
        loading: this.loading
      })
    },
    _pageProps () {
      return Object.assign({}, this.pageProps, {
        total: this.total,
        current: this.current,
        pageSize: this.pageSize
      })
    }
  },
  created () {
    this.setSort()
  },
  methods: {
    // 清除column sortMethod方法  设置orderKey order 初始值
    setSort () {
      let orderKey, order
      const props = _.cloneDeep(this.tableProps)
      this.tableProps.columns.forEach(column => {
        if (column.sortMethod && column.sortable) {
          this.sortFuncMap[column.key] = column.sortMethod
          if (column.sortType) {
            if (orderKey || order) {
              throw new Error('同时只能支持一个column排序')
            }
            orderKey = column.key
            order = column.sortType
          }
          delete column['sortMethod']
        }
      })
      this.processedTableProps = props
      this.orderKey = orderKey
      this.order = order
    },
    onSortChange ({key, order}) {
      this.orderKey = key
      this.order = order
      this.setCurrent(1)
    },
    onSelectionChange: function (selection) {
      this.$emit('on-select', selection)
    },
    onSizeChange: function (val) {
      this.pageSize = val
      this.setCurrent(1)
    },
    setCurrent (page) {
      // 换页时清空之前的选择
      this.onSelectionChange([])
      this.current = page
      this.reloadTableData()
    },
    setData () {
      this.total = this.tableData.length
      let data = this.tableData
      if (this.sortable) {
        const newData = _.cloneDeep(this.tableData)
        data = newData.sort((a, b) => {
          const func = this.sortFuncMap[this.orderKey]
          return this.order === 'asc' ? func(a, b) : func(b, a)
        })
      }
      this.data = data.slice(
        (this.current - 1) * this.pageSize,
        this.current * this.pageSize
      )
    },
    reloadTableData () {
      if (this.isAsync) {
        const sortProps = {current: this.current, pageSize: this.pageSize}
        if (this.sortable) {
          sortProps.orderKey = this.orderKey
          sortProps.order = this.order
        }
        this.loading = true
        this.tableData(sortProps)
          .then(({tableData, total}) => {
            this.data = tableData
            this.total = total
            this.loading = false
          })
          .catch(() => {
            this.data = []
            this.total = 0
            this.$Message.error('加载表格数据出错')
            this.loading = false
          })
      } else {
        this.setData()
      }
    }
  },
  mounted () {
    this.reloadTableData()
  },
  watch: {
    'tableData': function () {
      this.reloadTableData()
    },
    'tableProps': function () {
      this.setSort()
    }
  },
  render: function (h) {
    const children = [
      h('Table', {
        props: this._tableProps,
        on: {
          'on-sort-change': this.onSortChange,
          'on-selection-change': this.onSelectionChange
        }
      })
    ]
    if (this.total > this.pageSize) {
      children.push(h('Page', {
        props: this._pageProps,
        on: {
          'on-change': this.setCurrent,
          '@on-page-size-change="changeSize': this.onSizeChange
        }
      }))
    }
    return h('div', children)
  }
}
// 前端分页表格配置

const data = {
  data: [],
  pageProps: {
    pageSize: 10
  },
  tableProps: {
    columns: [
      { title: 'IOC', key: 'ioc' },
      { title: 'IP地址', key: 'ip' },
      {
        title: '命中数量',
        key: 'count',
        width: 120,
        sortable: true,
        sortType: 'desc',
        sortMethod (a, b) {
          return Number(a.count) - Number(b.count)
        }
      },
      { title: '地理位置', key: 'location' }
    ]
  }
}
<template>
  <div>
    <page-table
      ref="table"
      :table-props="tableProps"
      :page-props="pageProps"
      :load-data="loadData"/>
  </div>
</template>

<script>
  import PageTable from '@/components/PageTableAsync'
  import nameMixin from './nameMixin'
  import json2csv from 'json2csv'
  import download from 'downloadjs'
  import http from '@/api'

  export default {
    components: {
      PageTable
    },
    mixins: [nameMixin(false)],
    data () {
      return {
        pageProps: {
          pageSize: 10
        },
        tableProps: {
          columns: [
            { title: '#', key: 'index', width: 40 },
            { title: '类型', key: 'type', width: 100 },
            { title: 'IOC', key: 'ioc' }, 
            {
              title: '命中数量',
              key: 'count',
              width: 120,
              sortable: true,
              sortType: 'desc',
              sortMethod (a, b) {
                return Number(a.count) - Number(b.count)
              }
            }
          ]
        },
        tableData: []
      }
    },
    methods: {
      loadNameData () {
        this.$refs.table.reloadTableData()
      },
      loadData ({ current, pageSize }) {
        return http.get('apt/campaign/ioc', {
          params: {
            name: this.name,
            limit: pageSize,
            page: current
          }
        }).then(data => {
          return {
            tableData: data.data.map((item, index) => Object.assign({}, item, { index })),
            total: data.total
          }
        })
      }
    }
  }
</script>