ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ATUI之table组件的使用记录

2022-09-16 19:01:15  阅读:291  来源: 互联网

标签:index return column type 组件 table data ATUI const


描述

原组件使用中的不足

1、点击全选:Computed property "isSelectAll" was assigned to but it has no setter.
2、使用table组件,设置表格固定高度:height会导致全选报错,去除此设置则正常。【全选与固定高度冲突】
3、没有全选标识,当全部选中时会触发on-select-all返回全部选中的数据,
而取消全选时则需要通过on-selection-change去判断返回的数组为空确认取消全选。
前提:on-select-all和on-selection-change同时存在】
4、开启optional选择标识,通过on-selection-change返回值确认全选/全不选。
5、表格高度属性支持Number / String	类型,却对String类型未做任何类型处理,直接使用,导致String类型值入参无效。
6、无法实现表格行或列的合并。
7、自定义扩展局限。

修复的问题

1、修复 Elements in iteration expect to have 'v-bind:key' directives.
2、限制 height 属性的类型为Number,并设置默认值为500

组件使用

<template>
    <div class="page-bg">
        <tt :size="tableSize"
            :stripe="true"
            :border="true"
            :optional="true"
            :columns="columns1" 
            :data="data3"
            :pagination="true"
            :page-size="10"
            :show-page-total="true"
            :show-page-sizer="true"
            :show-page-quickjump="true"
            :height="432"
            @on-selection-change="handleSelectionChange"
            @on-page-change="handlePageChange"
            @on-page-size-change="handlePageSizeChange"></tt>
    </div>
</template>

<script>
import tt from '../components/table/src/table'
export default {
    data () {
        return {
            tableSize: 'large', // small normal
            columns1: [
                {
                    title: '姓名',
                    key: 'name'
                },
                {
                    title: '年龄',
                    key: 'age',
                    sortType: 'normal',
                    render: (a, row) => {
                        return a('AtTag',{
                            props: {
                                color: row.item.age > 20 ? 'success' : 'yellow'
                            }
                        }, row.item.age)
                    }
                },
                {
                    title: '地址',
                    key: 'address',
                    render: (t, row) => {
                        return t('p', {
                            style: {
                                width: '150px'
                            },
                            class: 'over-text'
                        }, row.item.address)
                    }
                },
                {
                    title: '操作',
                    render: (h, params) => {
                        return h('div', [
                            h('AtButton', {
                                props: {
                                    size: 'small',
                                    hollow: true
                                },
                                style: {
                                    marginRight: '8px'
                                },
                                on: {
                                    click: () => {
                                        this.$Message(params.item.name)
                                    }
                                }
                            }, '查看姓名'),
                            h('AtButton', {
                                props: {
                                    size: 'small',
                                    hollow: true
                                },
                                on: {
                                    click: () => {
                                        this.$Message(params.item.address)
                                    }
                                }
                                }, '查看地址')
                        ])
                    }
                }
            ],
            data3: this.makePageData(),
            selectAllList: []
        }
    },
    computed:{
    },
    components: {
        tt
    },
    methods: {
        makePageData () {
            const data = [
                {
                name: '库里',
                age: 18,
                address: '深圳市宝安区创业一路|深圳市宝安区创业一路深圳市宝安区创业一路深圳市宝安区创业一路深圳市宝安区创业一路'
                },
                {
                name: '詹姆斯',
                age: 25,
                address: '广州市天河区岗顶'
                },
                {
                name: '科比',
                age: 24,
                address: '上海市浦东新区'
                },
                {
                name: '杜兰特',
                age: 22,
                address: '深圳市南山区深南大道'
                },
                {
                name: '威斯布鲁克',
                age: 21,
                address: '北京市朝阳区'
                },
                {
                name: '邓肯',
                age: 26,
                address: '深圳市罗湖区万象城'
                },
                {
                name: '帕克',
                age: 25,
                address: '深圳市福田区中心书城'
                },
                {
                name: '欧文',
                age: 20,
                address: '广州市番禺区大学城'
                },
                {
                name: '托马斯',
                age: 19,
                address: '北京市朝阳区'
                }
            ]
            let pageData = []

            for (let i = 0; i < 5; i++) {
                pageData = pageData.concat(data)
            }

            return pageData
        },
        handleSelectionChange(rows) {
            console.log('handleSelectionChange==', rows);
            
        },
        handleSelectAll(list) {
            console.log('handleSelectAll==', list);
            
        },
        handlePageChange(page) {
            console.log('handlePageChange==', page);
            
        },
        handlePageSizeChange(size) {
            console.log('handlePageSizeChange==', size);
            
        }
    }
}
</script>

<style>
.over-text{
    text-overflow:ellipsis;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}
</style>

容错后的组件

<template>
  <div
    class="at-table"
    :class="{
      'at-table--fixHeight': this.height,
      'at-table--stripe': this.stripe,
      [`at-table--${this.size}`]: this.size,
      [`at-table--border`]: this.border
    }"
    :style="tableStyles">

    <!-- S Content -->
    <div class="at-table__content" :style="contentStyle">
      <!-- S Header -->
      <div class="at-table__header" v-if="height">
        <table>
          <colgroup>
            <col v-for="(column, index) in columnsData" :key="index" :width="setCellWidth(column, index)">
          </colgroup>
          <thead class="at-table__thead" ref="header">
            <tr>
              <!-- S Checkbox -->
              <th v-if="optional" class="at-table__cell at-table__column-selection">
                <at-checkbox v-model="isSelectAll" @click.native.prevent="handleSelectAll"></at-checkbox>
              </th>
              <!-- E Checkbox -->
              <!-- S Column th -->
              <th
                v-for="(column, index) in columnsData"
                class="at-table__cell at-table__column"
                :key="index"
                :class="column.className"
                :style="{
                  cursor: column.sortType ? 'pointer' : 'text'
                }"
                @click="column.sortType && handleSort(index)">
                {{ column.title }}
                <template v-if="column.sortType">
                  <div class="at-table__column-sorter"
                    :class="{
                      'sort-asc': column._sortType === 'asc',
                      'sort-desc': column._sortType === 'desc'
                    }">
                    <span class="at-table__column-sorter-up" @click.stop="handleSort(index, 'asc')"><i class="icon icon-chevron-up"></i></span>
                    <span class="at-table__column-sorter-down" @click.stop="handleSort(index, 'desc')"><i class="icon icon-chevron-down"></i></span>
                  </div>
                </template>
              </th>
              <!-- E Column th -->
            </tr>
          </thead>
        </table>
      </div>
      <!-- E Header -->

      <!-- S Body -->
      <div class="at-table__body" :style="bodyStyle">
        <table>
          <colgroup>
            <col v-for="(column, index) in columnsData" :key="index" :width="setCellWidth(column, index)">
          </colgroup>
          <thead class="at-table__thead" v-if="!height" ref="header">
            <tr>
              <!-- S Checkbox -->
              <th v-if="optional" class="at-table__cell at-table__column-selection">
                <at-checkbox v-model="isSelectAll" @click.native.prevent="handleSelectAll"></at-checkbox>
              </th>
              <!-- E Checkbox -->
              <!-- S Column th -->
              <th
                v-for="(column, index) in columnsData"
                class="at-table__cell at-table__column"
                :key="index"
                :class="column.className"
                :style="{
                  cursor: column.sortType ? 'pointer' : 'text'
                }"
                @click="column.sortType && handleSort(index)">
                {{ column.title }}
                <template v-if="column.sortType">
                  <div class="at-table__column-sorter"
                    :class="{
                      'sort-asc': column._sortType === 'asc',
                      'sort-desc': column._sortType === 'desc'
                    }">
                    <span class="at-table__column-sorter-up" @click.stop="handleSort(index, 'asc')"><i class="icon icon-chevron-up"></i></span>
                    <span class="at-table__column-sorter-down" @click.stop="handleSort(index, 'desc')"><i class="icon icon-chevron-down"></i></span>
                  </div>
                </template>
              </th>
              <!-- E Column th -->
            </tr>
          </thead>

          <tbody class="at-table__tbody" v-if="sortData.length" ref="body">
            <template v-for="(item, index) in sortData">
              <tr :key="index">
                <td v-if="optional" class="at-table__cell at-table__column-selection">
                  <at-checkbox v-model="objData[index].isChecked" @on-change="changeRowSelection"></at-checkbox>
                </td>
                <td v-for="(column, cindex) in columns" :key="cindex" class="at-table__cell">
                  <template v-if="column.render">
                    <Cell :item="item" :column="column" :index="index" :render="column.render"></Cell>
                  </template>
                  <template v-else>
                    {{ item[column.key] }}
                  </template>
                </td>
              </tr>
            </template>
          </tbody>

          <tbody class="at-table__tbody" v-else>
            <tr>
              <td class="at-table__cell at-table__cell--nodata" :colspan="optional ? columns.length + 1 : columns.length">
                <slot name="emptyText">{{ t('at.table.emptyText') }}</slot>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!-- E Body -->
    </div>
    <!-- E Content -->

    <!-- S Pagination -->
    <div v-if="pagination && total" class="at-table__footer" ref="footer">
      <at-pagination
        :current="currentPage"
        :size="size"
        :total="total"
        :page-size="pageSize"
        :show-total="showPageTotal"
        :show-sizer="showPageSizer"
        :show-quickjump="showPageQuickjump"
        @page-change="pageChange"
        @pagesize-change="pageSizeChange"></at-pagination>
    </div>
    <!-- E Pagination -->
  </div>
</template>

<script>
import Locale from 'at-ui/src/mixins/locale'
import { getStyle, deepCopy } from 'at-ui/src/utils/util'
import Cell from './render'
import Checkbox from 'at-ui/src/components/checkbox'
import Pagination from 'at-ui/src/components/pagination'

export default {
  name: 'AtTable',
  components: {
    Checkbox,
    Pagination,
    Cell
  },
  mixins: [Locale],
  props: {
    size: {
      type: String,
      default: 'normal'
    },
    stripe: {
      type: Boolean,
      default: false
    },
    border: {
      type: Boolean,
      default: false
    },
    data: {
      type: Array,
      default () {
        return []
      }
    },
    columns: {
      type: Array,
      default () {
        return []
      }
    },
    optional: {
      type: Boolean,
      default: false
    },
    pagination: {
      type: Boolean,
      default: false
    },
    pageSize: {
      type: Number,
      default: 10
    },
    showPageTotal: {
      type: Boolean,
      default: true
    },
    showPageSizer: {
      type: Boolean,
      default: false
    },
    showPageQuickjump: {
      type: Boolean,
      default: false
    },
    height: [Number]
  },
  data () {
    return {
      objData: this.makeObjData(), // use for checkbox to select all
      sortData: [], // use for sort or paginate
      allData: [],
      columnsData: this.makeColumns(),
      total: 0,
      bodyHeight: 0,
      pageCurSize: this.pageSize,
      columnsWidth: {},
      currentPage: 1
    }
  },
  watch: {
    height () {
      this.calculateBodyHeight()
    },
    allData () {
      this.total = this.allData.length
    },
    sortData () {
      this.handleResize()
    },
    pageCurSize () {
      this.sortData = this.makeDataWithPaginate()
    },
    data () {
      this.sortData = this.makeDataWithSortAndPage()
    }
  },
  computed: {
    tableStyles () {
      const styles = {}

      if (this.height) {
        styles.height = `${this.height}px`
      }
      if (this.width) {
        styles.width = `${this.width}px`
      }

      return styles
    },
    isSelectAll () {
      let isAll = true
      if (!this.sortData.length) {
        isAll = false
      }
      for (let i = 0, len = this.sortData.length; i < len; i++) {
        if (!this.objData[this.sortData[i].index].isChecked) {
          isAll = false
          break
        }
      }

      return isAll
    },
    bodyStyle () {
      const styles = {}
      if (this.bodyHeight !== 0) {
        const headerHeight = parseInt(getStyle(this.$refs.header, 'height')) || 0
        styles.height = `${this.bodyHeight}px`
        styles.marginTop = `${headerHeight}px`
      }
      return styles
    },
    contentStyle () {
      const styles = {}
      if (this.bodyHeight !== 0) {
        const headerHeight = parseInt(getStyle(this.$refs.header, 'height')) || 0
        styles.height = `${this.bodyHeight + headerHeight}px`
      }
      return styles
    }
  },
  methods: {
    calculateBodyHeight () {
      if (this.height) {
        this.$nextTick(() => {
          const headerHeight = parseInt(getStyle(this.$refs.header, 'height')) || 0
          const footerHeight = parseInt(getStyle(this.$refs.footer, 'height')) || 0

          this.bodyHeight = this.height - headerHeight - footerHeight
        })
      } else {
        this.bodyHeight = 0
      }
    },
    makeColumns () {
      const columns = deepCopy(this.columns)
      columns.forEach((column, idx) => {
        column._index = idx
        column._sortType = 'normal'

        if (column.sortType) {
          column._sortType = column.sortType
          column.sortType = column.sortType
        }
      })
      return columns
    },
    makeData () {
      const data = deepCopy(this.data)
      data.forEach((row, idx) => {
        row.index = idx
      })
      return data
    },
    makeObjData () {
      const rowData = {}

      this.data.forEach((row, index) => {
        const newRow = deepCopy(row)

        newRow.isChecked = !!newRow.isChecked

        rowData[index] = newRow
      })

      return rowData
    },
    makeDataWithSortAndPage (pageNum) {
      let data = []
      let allData = []

      allData = this.makeDataWithSort()
      this.allData = allData

      data = this.makeDataWithPaginate(pageNum)
      return data
    },
    makeDataWithPaginate (page) {
      page = page || 1
      const pageStart = (page - 1) * this.pageCurSize
      const pageEnd = pageStart + this.pageCurSize
      let pageData = []

      if (this.pagination) {
        pageData = this.allData.slice(pageStart, pageEnd)
      } else {
        pageData = this.allData
      }
      return pageData
    },
    makeDataWithSort () {
      let data = this.makeData()
      let sortType = 'normal'
      let sortIndex = -1

      for (let i = 0, len = this.columnsData.length; i < len; i++) {
        if (this.columnsData[i].sortType && this.columnsData[i].sortType !== 'normal') {
          sortType = this.columnsData[i].sortType
          sortIndex = i
          break
        }
      }

      if (sortType !== 'normal') {
        data = this.sort(data, sortType, sortIndex)
      }

      return data
    },
    handleSelectAll () {
      const status = !this.isSelectAll

      for (const data of this.sortData) {
        this.objData[data.index].isChecked = status
      }

      const selection = this.getSelection()

      status && this.$emit('on-select-all', selection)
      this.$emit('on-selection-change', selection)
    },
    handleSort (index, type) {
      const key = this.columnsData[index].key
      const sortType = this.columnsData[index]._sortType
      const sortNameArr = ['normal', 'desc', 'asc']

      if (this.columnsData[index].sortType) {
        if (!type) {
          const tmpIdx = sortNameArr.indexOf(sortType)
          if (tmpIdx >= 0) {
            type = sortNameArr[(tmpIdx + 1) > 2 ? 0 : tmpIdx + 1]
          }
        }
        if (type === 'normal') {
          this.sortData = this.makeDataWithSortAndPage(this.currentPage)
        } else {
          this.sortData = this.sort(this.sortData, type, index)
        }
      }
      this.columnsData[index]._sortType = type

      this.$emit('on-sort-change', {
        column: JSON.parse(JSON.stringify(this.columns[this.columnsData[index]._index])),
        order: type,
        key
      })
    },
    sort (data, type, index) {
      const key = this.columnsData[index].key
      data.sort((a, b) => {
        if (this.columnsData[index].sortMethod) {
          return this.columnsData[index].sortMethod(a[key], b[key], type)
        } else if (type === 'asc') {
          return a[key] > b[key] ? 1 : -1
        }
        return a[key] < b[key] ? 1 : -1
      })
      return data
    },
    getSelection () {
      const selectionIndexArray = []
      for (const i in this.objData) {
        if (this.objData[i].isChecked) {
          selectionIndexArray.push(i | 0)
        }
      }
      return JSON.parse(JSON.stringify(this.data.filter((data, index) => selectionIndexArray.indexOf(index) > -1)))
    },
    changeRowSelection () {
      const selection = this.getSelection()
      this.$emit('on-selection-change', selection)
    },
    pageChange (page) {
      this.$emit('on-page-change', page)
      this.currentPage = page
      this.sortData = this.makeDataWithPaginate(page)
    },
    pageSizeChange (size) {
      this.$emit('on-page-size-change', size)
      this.pageCurSize = size
    },
    handleResize () {
      this.$nextTick(() => {
        const columnsWidth = {}

        if (this.data.length) {
          const $td = this.$refs.body.querySelectorAll('tr')[0].querySelectorAll('td')

          for (let i = 0; i < $td.length; i++) {
            const column = this.columnsData[i]
            let width = parseInt(getStyle($td[i], 'width'))

            if (column) {
              if (column.width) {
                width = column.width
              }
              columnsWidth[column._index] = { width }
            }
          }
        }

        this.columnsWidth = columnsWidth
      })
    },
    setCellWidth (column, index) {
      let width = ''

      if (column.width) {
        width = column.width
      } else if (this.columnsWidth[column._index]) {
        width = this.columnsWidth[column._index].width
      }

      width = width === '0' ? '' : width
      return width
    }
  },
  created () {
    this.sortData = this.makeDataWithSortAndPage()
  },
  mounted () {
    this.calculateBodyHeight()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestory () {
    window.removeEventListener('resize', this.handleResize)
  }
}
</script>

标签:index,return,column,type,组件,table,data,ATUI,const
来源: https://www.cnblogs.com/min77/p/16700980.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有