vue2 el-table 封装

vue2 el-table 封装

  1. 在 custom 文件夹下面创建 tableList.vue
  2. 直接上代码(代码比较多,复制可直接用)
javascript 复制代码
<template>
  <div class="mp-list">
    <el-table
      ref="multipleTable"
      class="mp-custom-table"
      :data="tableData"    
      v-loading="fullLoading"
      :highlight-current-row="highlightCurrentRow"
      :row-class-name="rowClassName"
      :border="isBorder"
      :reserve-selection="false"
      @row-click="handleClickRow"
      @current-change="handleCurrentChange"
      :row-key="rowKey"
      :default-expand-all="defaultExpandAll"
      :expand-row-keys="expandRowKeys"
      @expand-change="expandChangeClick"
      @header-click="handleClickHeader"
      doLayout
      :stripe="true"
      :default-sort="defaultSort"
      @selection-change="handleSelectionChange"
      @filter-change="filterChangeFn"
      @row-dblclick="ondblclick"
      width="100%"
      :height="tableHeight"
      :max-height="maxHeight"
      @select="select"
      @select-all="selectAll"
      :header-cell-style="headerCellStyle"
      @cell-mouse-enter="cellMouseEnter"
      @cell-mouse-leave="cellMouseLeave"
      @sort-change="sortChange"
      :key="statusKey"
    >
      <el-table-column v-if="selecShow" :align="selecShowAlign" :selectable="selectable" type="selection" width="60"></el-table-column>
      <el-table-column v-if="needSerialNumber" type="index" :label="serialNumberName"></el-table-column>
      // 行详情插槽
      <template v-if="expand">
        <slot name="expand"></slot>
      </template>
      <!-- theadData 配置项加了showOverTip字段,控制当前列是否使用tooltip,不传默认原来true -->
      <template v-for="(item, idx) of theadData">
        <el-table-column
          :label="item.title"
          :width="item.width"
          :prop="item.field"
          :sortable="item.sortable"
          :key="`${item.field || item.prop}_${idx}`"
          :min-width="item.minWidth"
          :align="cellAlign"
          :class-name="item.highlight ? 'mp-highlight' : ''"
          :sort-by="item.sortBy"
          :filter-placement="'bottom'"
          :filters="item.filters"
          :filter-method="item.filterMethod"
          :filter-multiple="false"
          :columnKey="item.field"
          :sort-method="item.sortFn"
          :show-overflow-tooltip="item.showOverTip !== undefined ? item.showOverTip : true"
        >
          <!-- 给列表的th添加提示icon,鼠标进过后显示tooltip,配置theadData时,配置headerTip内容,则展示到此,未配置不展示icon -->
          <template slot="header" v-if="item.headerTip">
            <span>
              {{ item.title }}
              <el-tooltip effect="dark" placement="top" :content="item.headerTip">
                <i class="el-icon-info"></i>
              </el-tooltip>
            </span>
          </template>

          <template slot-scope="scope">
            <slot v-if="item.isSlot" :name="item.field" :scope="scope" :row="scope.row" :column="scope.column" :store="scope.store" :_self="scope._self"></slot>
            <div v-else>
              <div v-if="item.htmlCustom && typeof item.htmlCustom === 'function'" v-html="item.htmlCustom(scope.row, scope.column, scope.row[item.field], item.field) || '--'"></div>
              <span v-else>{{ fieldDeel(scope.row, item.field) || '--' }}</span>
            </div>
          </template>
        </el-table-column>
      </template>

      <template slot="empty">
        <div class="mp_tatble_nodata">
           // 表格数据为空时,显示暂无数据图片
           // 图片根据自己的主题,更换合适的图片
          <img class="mp_noData_image" src='/img/dark_no_data.png' alt />
          <p class="mp_tatble_txt">暂无数据</p>
        </div>
      </template>

      <slot name="slotTip"></slot>
      <slot name="operbtn"></slot>
			<!-- other 是为了处理表格列key在某个子对象下,父组件正常循环 -->
			<slot name="other"></slot>
    </el-table>
  </div>
</template>

<script>
export default {
  name: 'tableList',
  props: {
    //表格高亮当前选中行
    highlightCurrentRow: {
      default: false,
    },
    expand: {
      type: Boolean,
      default: false,
    },
    rowKey: {
      type: String,
      default: 'id',
    },
    expandRowKeys: {
      type: Array,
      default: () => [],
    },
    // table高度,接收String
    tableHeight: {
      default: false,
    },
    maxHeight: {
      type: String,
      default: '100%',
    },
    tableData: Array, // 表格内容
    theadData: {
      type: Array,
    }, // 表头内容
    fullLoading: Boolean, // 加载遮罩
    sid: String,
    selecShow: {
      // 是否有选择框
      type: Boolean,
      default: false,
    },
    selecShowAlign: {
      type: String,
      default: 'left'
    },
    isBorder: {
      type: Boolean,
      default: true,
    },
    bk_obj_name: '',
    cellAlign: {
      type: String,
      default: 'left',
    },
    //设置表头样式
    headerCellStyle: {
      type: Object,
    },
    serialNumberName: {
      type: String,
      default: '序号',
    },
    needSerialNumber: {
      type: Boolean,
      default: false,
    },
    defaultExpandAll: {
      type: Boolean,
      default: false,
    },
    // 默认排序
    defaultSort: {
      type: Object,
      default: {
        prop: 'date',
      },
    },
    rowClassName: {
      type: Function,
    },
  },

  data() {
    return {
      idSelection: [],
      statusKey: 0,
    }
  },
  created() {},
  methods: {
    fieldDeel(row, field) {
      let arr = field.split('.')
      let text = row
      arr.forEach((item) => {
        text = text[item]
      })
      if (text == 0) {
        text = text + ''
      }
      return text
    },
    handleClickHeader(col, e) {
      // 点击某一表头
      if (col && col.sortable) {
      }
    },
    filterChangeFn(filter) {
      if (typeof this.$parent.getFilterValueFn === 'function') {
        this.$parent.getFilterValueFn(filter)
      }
    },
    handleClickRow(row, col, e) {
      //点击某一行跳转
      if (col && col.className) {
        if (col.className == 'mp-highlight') {
          this.$emit('handleClickRow', row, col, this.bk_obj_name)
        }
      }
    },
    ondblclick(row, col, e) {
      // 某一行的双击事件
      this.$emit('ondblclick', row, col)
    },
    toggleSelection(rows, selected) {
      this.$nextTick(() => {
        if (rows) {
          rows.forEach((row) => {
            this.$refs.multipleTable.toggleRowSelection(row, selected)
          })
        } else {
          this.$refs.multipleTable.clearSelection()
        }
      })
    },
    // 单行设置高亮
    setCurrentRowHandel(row) {
      this.$nextTick(() => {
        this.$refs.multipleTable.setCurrentRow(row[0])
      })
    },
    refreshLayout() {
      this.$nextTick(() => {
        this.$refs.multipleTable.doLayout()
      })
    },
    // 展开航
    expandChangeClick(row, expandRow) {
      this.$emit('expandChange', row, expandRow)
    },
    handleSelectionChange(val) {
      // 多选
      this.idSelection = []
      val.forEach((item) => {
        this.idSelection.push(item[this.sid])
      })
      this.$emit('changeData', this.idSelection, val)
      this.$emit('queryRow', val)
    },
    selectable(row, index) {
      // 是否禁用多选
      let state = true
      if (row.typeFlagOrganization) {
        state = !row.typeFlagOrganization
      }
      return state
    },
    // 手动勾选数据行的 Checkbox 时触发的事件
    select(selection, row) {
      this.$emit('select', selection, row)
    },
    selectAll(selection) {
      this.$emit('select-all', selection)
    },
    cellMouseEnter(row, column, cell, event) {
      this.$emit('cell-mouse-enter', { row, column, cell, event })
    },
    cellMouseLeave(row, column, cell, event) {
      this.$emit('cell-mouse-leave', { row, column, cell, event })
    },
    // 点击表格行时选中
    handleCurrentChange(row) {
      // this.$refs.multipleTable.toggleRowSelection(row)
      if (this.highlightCurrentRow) {
        //有高亮效果可单选 ---平面图资产关联使用
        this.$emit('handleCurrentChange', row)
      }
    },
    formatterCellval(row, column, cellValue, index) {
      // 没有内容时的占位符,暂时无用
      if (typeof this.$parent.customFormatterCellval === 'function') {
        // 判断外部是否有customFormatterCellval方法
        const value = this.$parent.customFormatterCellval(row, column, cellValue, index)
        return value
      } else {
        // 没有-赋值给表格
        if (!Boolean(cellValue)) {
          return '--'
        } else {
          return cellValue
        }
      }
    },
    // 排序方法
    sortFn(a, b) {},
    // 监听排序事件
    sortChange(data) {
      this.$emit('sort-change', data)
    },
  },
  watch: {
    theadData: {
      handler(vv) {},
      deep: true,
    }
  },
}
</script>

<style>
.el-table__body-wrapper tr:hover .mp-highlight {
  color: #2579ff;
  cursor: pointer;
}

.el-tooltip__popper {
  max-width: 800px;
}

td.mp-highlight:hover {
  color: #2579ff;
  cursor: pointer;
}

.el-table__header thead th .cell .el-table__column-filter-trigger i.el-icon-arrow-down {
  position: absolute;
  top: 6px;
  left: auto;
  color: #666;
  transform: scale(1);
}

.el-table__header thead th .cell .el-table__column-filter-trigger i.el-icon-arrow-down:before {
  content: '\e790';
}

.mp-custom-table {
  font-size: 14px;
  /* border-radius:10px; */
}

.el-table__header-wrapper {
  border-radius: 0;
}

.el-table__header-wrapper .cell .el-icon-info {
  cursor: pointer;
  opacity: 0.4;
}
.el-table__header-wrapper .cell .el-icon-info:hover {
  opacity: 0.8;
}

/* .el-table__body-wrapper{
  border-radius:10px;
} */

.el-table--border th {
  border-right: none;
}

.el-table--border td {
  border-right: none;
}

.mp-custom-table .el-table--striped .el-table__body tr.el-table__row--striped td {
  background-color: RGBA(247, 248, 252, 1) !important;
}

.mp-list.mp-custom-table .el-table__body-wrapper tr:hover td {
  background-color: RGBA(231, 244, 255, 1) !important;
}

.mp-custom-table .el-table--border,
.el-table--group {
  border-left: none;
  border-right: none;
  border-top: none;
}

.mp-custom-table .el-table--border::after,
.el-table--group::after,
.el-table::before {
  background-color: transparent !important;
}

.mp-custom-table.el-table .el-table__body-wrapper {
  padding-bottom: 0px;
}

.mp-custom-table.el-table .el-table__fixed-right {
  height: calc(100% - 10px) !important;
}

.mp-custom-table.el-table .el-table__fixed-right::before {
  background-color: transparent !important;
}

.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar {
  width: 5px;
  height: 8px;
  background-color: #fff;
  border-radius: 5px;
  border-left: none;
}

.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-track,
.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
  border-radius: 999px;
}

.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-track {
  box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.2) inset;
}

.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-thumb {
  background-clip: content-box;
  background: rgba(0, 0, 0, 0.01);
  box-shadow: none;
}

/* .el-table.mp-custom-table
  .el-table__body-wrapper:hover::-webkit-scrollbar-thumb {
  background: red;
} */

.el-table.mp-custom-table .el-table__body-wrapper::-webkit-scrollbar-corner {
  background: transparent;
}

.mp_tatble_nodata {
  /* padding: 40px 0; */
  display: flex;
  align-items: center;
  flex-flow: column;
  justify-content: center;
}

.mp_noData_image {
  width: 80px;
  height: 80px;
}

.mp_tatble_txt {
  font-size: 14px !important;
}
</style>
<style>
.mp-list.mp-custom-table .el-table__header thead tr th {
  background: rgba(242, 244, 248, 1) !important;
  color: rgba(68, 79, 89, 1) !important;
}
.eveningTheme .el-table__body-wrapper tr:hover .mp-highlight {
  color: #07f6ff !important;
}
</style>
<style lang="scss" scoped>
.eveningTheme {
  .el-table__body-wrapper tr:hover .mp-highlight {
    color: #07f6ff !important;
  }
  .mp-custom-table ::v-deep .el-table__header thead tr th {
    background: #062540 !important;
    // color:#fff !important;
  }

  .mp-custom-table {
    ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped td {
      background-color: #062540 !important;
    }

    ::v-deep .el-table__body-wrapper tr:hover td,
    ::v-deep .el-table--striped .el-table__body tr.el-table__row--striped:hover td {
      background-color: #153864 !important;
    }

    ::v-deep .el-table__body-wrapper tr:hover .mp-highlight {
      color: #07f6ff;
      cursor: pointer;
    }

    ::v-deep td.mp-highlight:hover td {
      color: #07f6ff;
      cursor: pointer;
    }

    ::v-deep .el-table__body-wrapper {
      &::-webkit-scrollbar {
        width: 5px;
        height: 5px;
        background-color: transparent;
        border-radius: 5px;
        border-left: none;

        &-track {
          background-color: #020919;
        }

        &-thumb {
          background-color: #07639d;
        }
      }
    }

    ::v-deep .el-table__body-wrapper:hover {
      &::-webkit-scrollbar {
        &-thumb {
          background-color: #153864;
        }
      }
    }

    ::v-deep.el-table {
      tr {
        background-color: #020919 !important;
      }
    }
  }
}
::v-deep .mp-disabled-row,
::v-deep .mp-list.mp-custom-table .el-table__body-wrapper tr.mp-disabled-row:hover,
::v-deep .mp-custom-table .el-table--striped .el-table__body tr.el-table__row--striped.mp-disabled-row {
  td {
    //border-top: 1px dashed rgba(62, 127, 255, 1);
    border-bottom: 1px dashed rgba(62, 127, 255, 1);
    background: rgba(62, 127, 255, 0.2) !important;
  }
}
</style>
<style lang="scss">
.eveningTheme {
  .mp-list.mp-custom-table .el-table__header thead tr th {
    background: #071d30 !important;
    // color:rgba(68, 79, 89, 1) !important;;
  }
}
</style>
  1. 组件简单使用 (基本常用的属性方法都已封装进去 , 可自行查看 tableList.vue )
    (如果缺少需要的功能,可自行补充,或者留言)
javascript 复制代码
/**
 :selecShow="true"    // 开启复选框
 :tableData="dataTableListInfo"   // 表格数据
 :theadData="option.column"  // 表格头部
 :fullLoading="loading"  // 表格loading
 @queryRow="selectDataTable"  // 表格多选事件
 @handleClickRow="getHandleClickRow"  // 行点击事件

*/
<template>
	<div>
		<table-operation
		 class="mp-custom-table"
		 :selecShow="true"
		 :tableData="dataTableListInfo"
		 :theadData="option.column"
		 :fullLoading="loading"
		 @queryRow="selectDataTable"
		 @handleClickRow="getHandleClickRow"
		 ref="tableRef"
		>
		  // 该字段使用了插槽  对数据做了处理
		 <template slot="keyNode" slot-scope="{ row }">
		   <span>{{ row['keyNode'] == 1 ? '否' : '是' }}</span>
		 </template>
		 // 表格按钮组
		 <el-table-column slot="operbtn" label="操作" width="160" fixed="right">
		   <template slot-scope="{ row }">
		   <mp-button type="text" class="mp-button_edit-custom mp-button_table-typeA-custom" @click="editFormTable(row)">编辑</mp-button>
		     <mp-button type="text" class="mp-button_edit-custom mp-button_table-typeA-custom" @click="deleteFormTable(row)">删除</mp-button>
		   </template>
		 </el-table-column>
		</table-operation>
		// 分页组件
		 <mp-pagination :pageIndex="pageIndex" :pageSize="pageSize" :total="total" @page-change="pageChange" @page-size-change="pageSizeChange"></mp-pagination>
	</div>
</template>
<script>
import TableOperation from '@/custom/tableList' // 引入上面的表格组件
export default {
  components: {
    TableOperation,
  },
  data() {
    return {
      dataTableList: [],
      loading: false,
      pageIndex: 1, //页码
      pageSize: 10, //分页条目数
	  total: 0, // 总条数
      option: {
	    column: [
	      {
	        field: 'indexName',
	        highlight: true,  // 鼠标移入表格行后,指标名称字段高亮   点击指标名称 跳转
	        title: '指标名称', 
	        //  给列表的th添加提示icon,鼠标进过后显示tooltip,配置theadData时,配置headerTip内容,则展示到此,未配置不展示icon
	        headerTip: '检测内容定义的名称',
	      },
	      {
	        field: 'indexCode',
	        title: '唯一标识',
	        headerTip: 'cmdb 中字段唯一标识',
	      },
	      {
	        field: 'keyNode',
	        title: '是否关键指标',
	        headerTip: '标记',
	        // 该字段是否使用插槽
	        isSlot: true, //插槽
	      }
	    ],
	  }, // 表头
    }
  },
  methods:{
        // 编辑
        editFormTable(row){},
	    deleteFormTable(row) {
	      // 这里是表格行删除事件
	    },
	        // 多选
	    selectDataTable(row, data) {
	     
	    },
	    // 每一行的指标名称点击事件
	    getHandleClickRow(row) {
		   	
		},
		 // 分页
	    pageChange(pageIndex) {
	      this.pageIndex = pageIndex
	    },
	    // 分页每页条数
	    pageSizeChange(pageSize) {
	      this.pageIndex = 1
	      this.pageSize = pageSize
	    },
	}
}
</script>
  1. 效果

  2. 扩展(分页组件)

    1. 在 custom 文件夹下 新建 mpPagination.vue
    2. 上代码
javascript 复制代码
// mpPagination.vue

<template>
  <!-- 分页 -->
  <div class="avue-crud__pagination">
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="pageIndex"
      :page-sizes="pageSizeOption"
      :page-size="pageSize"
      :pager-count="showPagingCount"
      :layout="layout"
      :total="total"
      :key="keyIndex"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  name: 'MpPagination',
  props: {
    index:{
      type:Number,
      default:0
    },
    //总条数
    total: {
      type: Number,
      default: 0,
    },
    //当前页
    pageIndex: {
      type: Number,
      default: 1,
    },
    //页码按钮的数量,当总页数超过该值时会折叠
    showPagingCount: {
      type: Number,
      default: 7,
    },
    //每页条目数
    pageSize: {
      type: Number,
      default: 10,
    },
    //配置功能布局
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper',
    },
    //选择每页条目数
    pageSizeOption: {
      type: Array,
      default() {
        return [10, 20, 50]
      },
    },
  },
  data() {
    return {
      keyIndex:0
    }
  },
  methods: {
    //每页条目数改变
    handleSizeChange(val) {
      this.$emit('page-size-change', val,this.index)
    },
    //当前页改变
    handleCurrentChange(val) {
      this.$emit('page-change', val,this.index)
    },
  },
}
</script>
  1. 以上为全部代码!
相关推荐
新中地GIS开发老师43 分钟前
25考研希望渺茫,工作 VS 二战,怎么选?
javascript·学习·考研·arcgis·地理信息科学·地信
萧大侠jdeps1 小时前
Vue 3 与 Tauri 集成开发跨端APP
前端·javascript·vue.js·tauri
JYeontu2 小时前
实现一个动态脱敏指令,输入时候显示真实数据,展示的时候进行脱敏
前端·javascript·vue.js
发呆的薇薇°2 小时前
react里使用Day.js显示时间
前端·javascript·react.js
嘤嘤嘤2 小时前
基于大模型技术构建的 GitHub Assistant
前端·github
KeepCatch2 小时前
CSS 动画与过渡效果
前端
跑跑快跑2 小时前
React vite + less
前端·react.js·less
web136885658712 小时前
ctfshow_web入门_命令执行_web29-web39
前端
GISer_Jing2 小时前
前端面试题合集(一)——HTML/CSS/Javascript/ES6
前端·javascript·html
清岚_lxn2 小时前
es6 字符串每隔几个中间插入一个逗号
前端·javascript·算法