自己封装一个VUE表格组件

直接上源码

<template>
  <table class="my_table" :style="tableStyle">
    <thead ref="header">
      <tr :style="theadStyle">
        <th v-for="(item, index) in new_columns" :key="item.unique || index"
             :style="{minWidth: typeof item.minWidth === 'number'?item.minWidth + 'px':item.minWidth,
             width: item.width + 'px',
             textAlign: item.headAlign || 'center'}"
             :title="item.title">
             <slot :name="item.slotHeader" :data="{...item,index}">
              {{item.title}}
             </slot>
        </th>
      </tr>
    </thead>
    <tbody :style="tbodyStyle" ref="tableTbody">
            <tr v-for="(item,index) in index_data" :key="(dataKey && item[dataKey]) || index" :style="newRowStyle(item,index)">
                <td v-for="(_item, _index) in new_columns" :key="_item.unique || _index"
                     :style="{minWidth: typeof _item.minWidth === 'number'?_item.minWidth + 'px':_item.minWidth,
                     width: _item.width + 'px',
                     textAlign: _item.textAlign || 'center'}">
                      <slot :name="_item.slot" :data="{...item}">
                        {{chooseKey(item,_item.key)}}
                      </slot>
                </td>
            </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  name: 'MyList',
  props: {
    /* TODO columns接受值: 对象数组
        title: 表头名称
        slotHeader: 表头插槽名称
        slot: 表体插槽
        unique: 默认索引值,必须唯一,便于vue优化
        key: 对应prop:{data}中数据的键值
        minWidth: 对应列最小宽度
    */
    columns: {
      type: Array,
      default: () => []
    },
    data: {
      type: Array,
      default: () => []
    },
    count: {//序号记数初值
      type: Number || String,
      default: 1
    },
    dataKey: {
      type: String,
      default: null
    },
    tbodyStyle: {//自定义tbody的style
      type: String,
      default: null
    },
    tableStyle: {
      type: String,
      default: null
    },
    theadStyle: {
      type: String,
      default: null
    },
    rowStyle: {//自定义tbody中tr的style
      default: null
    }
  },
  computed: {
    new_columns () {//默认值并入columns
      let newArr = []
      for (let i = 0; i < this.columns.length; i++) {
        newArr[i] = JSON.parse(JSON.stringify(this.columns[i]))
        for (let j = 0; j < this.columns_list.length; j++) {
          if (this.columns[i].title === this.columns_list[j].title) {
            newArr[i] = (Object.assign(JSON.parse(JSON.stringify(this.columns_list[j])), this.columns[i]))
            break
          }
        }
      }
      return newArr
    },
    index_data () {//序号处理
      let newArr = this.data
      newArr.map((item, index) => {
        item.C_INDEX = index + (this.count * 1)
      })
      return newArr
    }
  },
  watch: {
  },
  data: () => ({
    columns_list: [//默认值
      {
        title: '序号',
        width: '60',
        key: 'C_INDEX'
      },
      {
        title: '版面',
        key: 'CHNLDESC',
        width: '80'
      },
      {
        title: '标题',
        key: 'TITLE',
        textAlign: 'left'
      },
      {
        title: '类型',
        key: 'DOCTYPE',
        width: '60'
      },
      {
        title: '稿件ID',
        key: 'METADATAID',
        width: '70'
      },
      {
        title: '栏目',
        key: 'CHNLDESC',
        width: '120'
      },
      {
        title: '操作人',
        key: 'TRUENAME',
        width: '86'
      },
      {
        title: '状态',
        key: 'STATUSNAME',
        width: '72'
      },
      {
        title: '最后版本时间',
        key: 'OPERTIME',
        width: '154'
      },
      {
        title: '点击量',
        key: 'HITS',
        width: '70'
      },
      {
        title: '流程版本时间',
        key: 'OPERTIME',
        width: '154'
      },
      {
        title: '焦点图标题',
        key: 'FOCUSIMGTITLE'
      },
      {
        title: '焦点图描述',
        key: 'FOCUSIMAGEDESC'
      },
      {
        title: '稿件标题',
        key: 'TITLE',
        textAlign: 'left'
      },
      {
        title: '渠道',
        width: '120'
      },
      {
        title: '字数',
        key: 'DOCWORDSCOUNT',
        width: '70'
      },
      {
        title: '创建人',
        key: 'TRUENAME',
        width: '90'
      },
      {
        title: '传稿人',
        key: 'OPERNAME',
        width: '90'
      },
      {
        title: '产品',
        key: ['SITEDESC', 'ACCOUNTNAME'],
        width: '90'
      },
      {
        title: '指派人',
        key: 'TRUENAME',
        width: '90'
      },
      {
        title: '所有者',
        key: 'OWNERTRUENAME',
        width: '86'
      },
      {
        title: '作者',
        key: 'AUTHOR_TRUENAME',
        width: '86'
      },
      {
        title: '修改时间',
        key: 'OPERTIME',
        width: '154'
      }
    ]
  }),
  methods: {
    evil (code) {
      let Fn = Function // 一个变量指向Function,防止有些前端编译工具报错
      return new Fn('return ' + code)()
    },
    newRowStyle (item, index) {//rowStyle处理
      if (typeof (this.rowStyle) === 'string') {
        return this.rowStyle
      } else if (typeof (this.rowStyle) === 'object' && (this.rowStyle.field && this.rowStyle.symbol && this.rowStyle.condition)) {
        if (this.evil("'" + this.chooseKey(item, this.rowStyle.field) + "'" + this.rowStyle.symbol + "'" + this.rowStyle.condition + "'")) {
          return this.rowStyle.style
        }
      }
    },
    chooseKey (item, keyArr) {//数组key处理
      if (Object.prototype.toString.call(keyArr) === '[object Array]') {
        for (let i = 0; i < keyArr.length; i++) {
          if (!(item[keyArr[i]] === '' || item[keyArr[i]] === undefined || item[keyArr[i]] === null)) {
            return item[keyArr[i]]
          }
        }
      } else if (Object.prototype.toString.call(keyArr) === '[object String]') {
        return item[keyArr]
      }
    }
  }
}
</script>
<style lang="less">
* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
    .my_table{
      width: 100%;
      height: 100%;
    }
    .my_table thead tr{
      border-top: 1px solid #eff1f4;
      color: #2a2a2a;
    }
    .my_table thead tr th{
      font-size: 16px;
      font-weight: 500;
      padding: 14px 0;
      padding-left: 5px;
      padding-right: 5px;
    }
    .my_table tbody{
      overflow-y: 'auto'
    }
    .my_table tbody tr:nth-child(odd) {
      background: #f4f6f7;
    }
    .my_table tbody tr {
      border-top: 1px solid #fff;
      border-bottom: 1px solid #fff;
      color: #3d3d3d;
      &:hover{
        background-color: #f4e0e1!important;
      }
    }
    .my_table  tbody tr td {
      padding-left: 3px;
      padding-right: 1px;
      padding-top: 7px;
      padding-bottom: 7px;
      font-size: 14px;
      text-align: center;
      word-break: break-all;
      height: 45px;
      min-height: 45px;
      max-height: 50px;
    }
</style>

参数表:
在这里插入图片描述
使用示例:

<template>
  <div class="ceshi">
    <CList :columns='columns' :data='data' tableStyle='' theadStyle='' tbodyStyle='' :rowStyle='rowStyle'>
      <template v-slot:TITLE='item'>
        <a class="title" href="../../">{{item.data.TITLE}}</a>
        <span class="mark" v-if="item.data.ORIGINAL==='1'" title="原创稿"></span>
      </template>
      <template v-slot:WEBSTATUSNAME='item'>
        <span v-if="item.data.WEBSTATUSNAME==='待编'" style="color: #ffbe5c;">{{item.data.WEBSTATUSNAME}}</span>
        <span v-else-if="item.data.WEBSTATUSNAME==='撤稿'" style="color: #d64541;">{{item.data.WEBSTATUSNAME}}</span>
      </template>
      <template v-slot:OPERTIME='item'>
        <a class="title" href="../../">{{item.data.OPERTIME}}</a>
      </template>
    </CList>
  </div>
</template>

<script>
import CList from '@/components/MyList'
export default {
  name: 'List',
  data: () => ({
    columns: [],
    data: [],
    rowStyle: {
      field: `WEBSTATUSNAME`,
      symbol: `===`,
      condition: `待修订`,
      style: 'color:#ccc'
    }
  }),
  components: {
    CList
  },
  mounted () {
    this.getData_dzbcs()
  },
  methods: {
    getData_dzbcs () {
      this.$axios.get('../../static/wangzhan.json').then(response => {
        this.columns = [
          {
            title: '序号'
          },
          {
            title: '稿件ID'
          },
          {
            title: '标题',
            slot: 'TITLE'
          },
          {
            title: '类型'
          },
          {
            title: '栏目'
          },
          {
            title: '操作人'
          },
          {
            title: '作者'
          },
          {
            title: '状态',
            slot: 'WEBSTATUSNAME',
            key: 'WEBSTATUSNAME'
          },
          {
            title: '最后版本时间',
            slot: 'OPERTIME'
          }
        ]
        this.data = response.data.DATA
      }, response => {
        console.log('error')
      })
    }
  }
}
</script>

<style lang="less" scoped>
.ceshi{
  width: 1713px;
}
a.title{
    vertical-align: middle;
    display: inline;
    overflow: hidden;
    line-height: 21px;
    display: initial;
    color: #3d3d3d;
    text-decoration: none;
    cursor: pointer;
    &:hover{
      color: #d64541;
    }
}
.mark{
    color: #c2c5cd;
    border-color: #c2c5cd;
    font-size: 11px;
    cursor: pointer;
    margin-left: 7px;
    display: inline-block;
    width: 16px;
    height: 16px;
    border: 1px solid;
    text-align: center;
    line-height: 16px;
    border-radius: 2px;
}
</style>

效果:
在这里插入图片描述

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值