用iview的表格方式封装element中的table表格和分页

因为经常做后台项目,需要使用表格分页,UI组件一直用的element,但是这个表格用起来感觉很乱,就像在写原生的table,而不像一个组件,没有iview的表格功能那么好用,iview表格是用一个data数据跟columns参数 就可以驱动整个表格,需要配置啥只用在columns里更改即可,方便完美,所以项目中一直加载了两个ui库,按需加载了iview的表格,其他的全部使用的cnd引入的element,简直不要太难受,所以就抽空,将element的表格按照iview的那种格式封装了一下。 大致是完成了,想要修改添加可自行修改。
放代码:
显示封装的组件代码

<template>
  <!-- element的table表格的组件 -->
  <div class="list_data">
    <div class="list_table">
      <el-table ref='tableBox' :size='size' :data="data" :border='border' :stripe='stripe' :max-height="height?height:null" :highlight-current-row='heightLinght' :show-header='showHeader' :empty-text='emptyText' :show-overflow-tooltip='showTooltip' :row-class-name="getRowClass" :cell-class-name='getCellClass' :header-cell-class-name='getHeadClass' @row-click='handRowClick' @selection-change="handleSelectionChange" style='width:100%'>
        <!-- 多选框 -->
        <el-table-column type="selection" width="55" v-if='multiple'></el-table-column>
        <!-- 单选框 -->
        <el-table-column width="55" v-if='radio'>
          <template slot-scope="scope">
            <el-radio v-model="radioValue" :label="scope.row[rowKey]">{{&nbsp;}}</el-radio>
          </template>
        </el-table-column>
        <!-- 序号 -->
        <el-table-column type="index" width="50" :label='indexLabel' v-if='index'></el-table-column>
        <!-- 其他数据 -->
        <el-table-column v-for='(item,index) in columns' :key='index' :prop="item.key" :label="item.title" :width="item.width" :fixed='item.fixed?item.fixed:null'>
          <template slot-scope="{row, column, $index}">
            <!-- 如果有插槽内容,则显示插槽 -->
            <template v-if="item.slot">
              <slot :name="item.slot" :row="row" :column="column" :index="$index"></slot>
            </template>
            <!-- 如果没有,则显示默认的数据 -->
            <template v-else>
              {{row[item.key]}}
            </template>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 分页功能 -->
    <div class="list_page" v-if='page'>
      <el-pagination :current-page="currentPage" :page-size="pageSize" :total="total" :page-sizes="pageSizeArr" :layout="layout" :pager-count="pagerCount" :background='background' :small='small' :hide-on-single-page='hideOn' @current-change="handleCurrentChange" @size-change="handleSizeChange"></el-pagination>
    </div>
  </div>
</template>

<script>
/*
@selectChange  暴露出去一个方法 返回的是单选或者多选的数据
@pageChange   分页的改变 不管是当前页数的改变 还是每页显示数量的改变都会触发 返回一个对象
    {
        currentPage: '',
        pageSize: ''
      }
*/
export default {
  // 下面这些就是所有的设置的参数
  props: {
    //   表格的数据  必传
    data: {
      type: Array,
      default: [],
    },
    // 表格的表头内容和对应的字段,还有是否定位 宽度等 必传
    /*
      columns:[
          {
            title: "名称",//表头
            key: "name",//对应的参数
            fixed:'left',//是否定位
            width:70,//宽度
            slot:'',//slot是作为插槽来用,自定义内容标签
          }
      ]
    */
    columns: {
      type: Array,
      default: []
    },
    // 表格是否显示序号 默认为显示
    index: {
      type: Boolean,
      default: true,
    },
    // 序号的标题设置
    indexLabel: {
      type: String,
      default: '序号'
    },
    // 表格是否显示边框 默认为显示
    border: {
      type: Boolean,
      default: true,
    },
    // 表格是否显示斑马条纹的颜色 默认为显示
    stripe: {
      type: Boolean,
      default: true,
    },
    // Table 的尺寸  medium / small / mini  默认为 medium
    size: {
      type: String,
      default: 'medium'
    },
    // 是否显示表头, 默认为显示
    showHeader: {
      type: Boolean,
      default: true,
    },
    //  是否高亮当前点击行  默认为false
    heightLinght: {
      type: Boolean,
      default: false,
    },
    // 默认情况下若内容过多会折行显示,为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。
    showTooltip: {
      type: Boolean,
      default: false,
    },
    // 表格最大高度,是需要固定表头的时候设置这个值 默认为空
    height: {
      type: [String, Number],
      default: ''
    },
    // 数据的唯一值,默认为id,在多选点击行选中 和 单选时 单选按钮选中时 需要使用这个值
    rowKey: {
      type: String,
      default: 'id',
    },
    // 表格是否需要作为单选,如果为单选,则会显示单选按钮  并返回一个方法来接受选择的数据 如果需要开启 则需要传递 rowKey  这个唯一值
    radio: {
      type: Boolean,
      default: false,
    },
    // 是否需要作为多选模式,默认为false,如果多选,则会显示多选框,并返回一个方法来接受选择的数据
    multiple: {
      type: Boolean,
      default: false,
    },
    // 这个主要是为多选时服务,是否在多选时点击行就选中数据,element默认是只能选中多选框才能选中数据,如果开启,则需要传递下面的rowKey,如果唯一值为id,则不需要,默认为id,
    rowSelect: {
      type: Boolean,
      default: false,
    },
    // 当没有数据时,需要展示的文字提示
    emptyText: {
      type: String,
      default: '暂无数据'
    },
    // 给某一行添加class添加样式 Function(row, rowIndex)/String 
    rowClassName: [String, Function],
    //  列的className的回调方法 Function(row, column, rowIndex, columnIndex)/String 
    cellClassName: [String, Function],
    // 表头单元格的 className 的回调方法, Function({row, rowIndex})/String
    headClassNmae: [String, Function],


    // 是否显示分页,默认为显示
    page: {
      type: Boolean,
      default: true,
    },
    // 当前显示的页数
    currentPage: {
      type: Number,
      default: 1,
    },
    // 每页显示的数量
    pageSize: {
      type: Number,
      default: 20,
    },
    // 总条数
    total: {
      type: Number,
      default: 0,
    },
    // 页码按钮的数量,当总页数超过该值时会折叠,大于等于 5 且小于等于 21 的奇数
    pagerCount: {
      type: Number,
      default: 5,
    },
    //每页显示个数选择器的选项设置
    pageSizeArr: {
      type: Array,
      default: [10, 20, 30, 40, 50, 100],
    },
    // 是否使用小型分页样式  默认为false
    small: {
      type: Boolean,
      default: false,
    },
    // 是否为分页按钮添加背景色  默认为true
    background: {
      type: Boolean,
      default: true,
    },
    // 	只有一页时是否隐藏  默认为false
    hideOn: {
      type: Boolean,
      default: false,
    },
    layout: {
      type: String,
      default: 'prev, pager, next,sizes, total,jumper'
    }
  },
  data() {
    return {
      radioValue: '',//单选按钮绑定的值
      selectList: [],//选中的值
    };
  },
  computed: {

  },

  watch: {

  },
  methods: {
    //   获取行的classname
    getRowClass({ row, rowIndex }) {
      var rowClass = this.rowClassName;
      if (typeof rowClass === 'string') {
        return rowClass;
      } else if (typeof rowClass === 'function') {
        return rowClass(row, rowIndex)
      }
    },
    // 获取列的className
    getCellClass({ row, column, rowIndex, columnIndex }) {
      var cellClass = this.cellClassName;
      if (typeof cellClass === 'string') {
        return cellClass;
      } else if (typeof cellClass === 'function') {
        return cellClass(row, column, rowIndex, columnIndex)
      }
    },
    // 获取表头的className
    getHeadClass({ row, rowIndex }) {
      var headClass = this.headClassNmae;
      if (typeof headClass === 'string') {
        return headClass;
      } else if (typeof headClass === 'function') {
        return headClass(row, rowIndex)
      }
    },
    // 点击多选框时的数据
    handleSelectionChange(val) {
      this.selectList = val;
      this.$emit('selectChange', this.selectList)
    },
    // 某一行被点击时
    handRowClick(row, column) {
      // 如果为单选时
      if (this.radio) {
        this.selectList = [];
        this.radioValue = row[this.rowKey];//将选中的值赋值用于单选按钮的选中
        this.$refs.tableBox.setCurrentRow(row);//单选时 element提供了一个方法 来使选中的高亮
        this.selectList.push(row);
        this.$emit('selectChange', this.selectList)
      }
      //如果为多选时,需要点击行来选中数据 rowSelect为true , rowKey为列表唯一值
      if (this.multiple && this.rowSelect && this.rowKey) {
        //   先判断点击的数据是否已在选中数据中存在 不过需要一个列表的唯一值来判断  默认为id
        let index = this.selectList.findIndex(item => {
          return item[this.rowKey] == row[this.rowKey]
        })
        if (index == -1) {
          // 如果未存在,设置已选状态
          this.$refs.tableBox.toggleRowSelection(row, true); //设置复选框为选中状态
        } else {
          // 如果已存在,设置未选状态
          this.$refs.tableBox.toggleRowSelection(row, false); //设置复选框为未选状态
        }
      }
    },
    //   选取页数
    handleCurrentChange(val) {
      this.currentPage = val;
      this.$emit('pageChange', {
        currentPage: this.currentPage,
        pageSize: this.pageSize
      })
    },
    // 选取每页显示的数量
    handleSizeChange(val) {
      var num = this.currentPage * val;
      if (this.total < num && this.total > 0) {
        this.currentPage = Math.ceil(this.total / val)
      }
      this.pageSize = val;
      this.$emit('pageChange', {
        currentPage: this.currentPage,
        pageSize: this.pageSize
      })

    },
  },
  mounted() {

  },
};
</script>

<style scoped lang="less">
// 这个样式是根据自己项目里需要写的,可以自己更改,用的flex
.list_data {
  flex: 1;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
  padding-bottom: 50px;

  .list_table {
    flex: 1;
    overflow: auto;

    .el-table {
      .el-table__body-wrapper {
        overflow: auto;

        // 表格的滚动条的样式
        &::-webkit-scrollbar {
          width: 10px;
          height: 10px;
        }

        &::-webkit-scrollbar-track {
          background: rgb(239, 239, 239);
          border-radius: 2px;
        }

        &::-webkit-scrollbar-thumb {
          background: #bfbfbf;
          border-radius: 10px;
        }
      }
    }

    &::-webkit-scrollbar {
      width: 8px;
      height: 5px;
    }

    &::-webkit-scrollbar-track {
      background: rgb(239, 239, 239);
      border-radius: 2px;
    }

    &::-webkit-scrollbar-thumb {
      background: #bfbfbf;
      border-radius: 10px;
    }

    // &::-webkit-scrollbar-thumb:hover {
    //     background: #2789ff;
    // }
  }

  .list_page {
    width: 100%;
    position: absolute;
    left: 0;
    bottom: 0;
    background: #fff;
    text-align: right;
  }
}
.list_table /deep/.el-table tr {
  color: #424142;
  font-size: 14px;
  font-family: "黑体";
  th {
    text-align: center;
    font-weight: bold;
    color: #666;
  }
  td {
    text-align: center;
    line-height: 1.3;
  }
}
</style>

组件代码已完成 自定义插槽是用的slot,没有用iview那样的render函数,感觉那样写起来好费劲。
下面的就是组件的使用

<template>
  <div class="list_box">
    <v-table :data='tableData' :columns='columns' radio :rowClassName='tableRowClassName' @selectChange='selectChange($event)' @pageChange='pageChange($event)'>
      <!-- 这地方是自定义的一个插槽  slot对应的colums定义的slot参数, slot-scope="scope" 必须要有 是接收组件返回的每行的数据-->
      <div slot='caozuo' slot-scope="scope">
        <button @click.stop="slotClick(scope)">点击</button>
      </div>
    </v-table>

  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
          id: 1,
        },
        {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄',
          id: 2,
        },
        {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄',
          id: 3,
        },
        {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1516 弄',
          id: 4,
        },
        {
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
          id: 5,
        },
        {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1517 弄',
          id: 6,
        },
        {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1519 弄',
          id: 7,
        },
        {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1516 弄',
          id: 8,
        },

      ],
      columns: [
        {
          title: "日期",
          key: "date",
          width: 180,
        },
        {
          title: "姓名",
          key: "name",
          width: 180,
        },
        {
          title: "地址",
          key: "address",
        },
        {
          title: "操作",
          slot: 'caozuo',
          width: 300,
        }
      ],
    };
  },
  methods: {
    //   这个是自定义按钮点击返回的数据
    slotClick(obj) {
      console.log(obj);
      //  {row: {…}, column: {…}, index: 2}
    },
    //   这个是表格多选返回的数据
    selectChange(data) {
      console.log(data);
    },
    // 这个是表格的rowClassName参数添加class  其他cellClassName  跟 headClassNmae 一样 ,
    tableRowClassName(row, rowIndex) {
      // 这里返回的class名自己在下面定义好样式
      if (rowIndex === 1) {
        return 'warning-row';
      } else if (rowIndex == 3) {
        return 'success-row';
      }
    },
    // 这个是分页的改变返回的内容
    pageChange(obj) {
      console.log(obj);
      //{currentPage: 1, pageSize: 30}
    }

  },
  mounted() {

  },
};
</script>

<style scoped lang="less">
// 这里就是 rowClassName 自定义的class的样式
.list_box /deep/.el-table .warning-row td {
  background: oldlace;
}

.list_box /deep/.el-table .success-row td {
  background: #f0f9eb;
}
</style>

到这就完事了,大概就这样了,刚写完,还有需要优化的地方,可自行修改自己需要的
下面放一张使用图
用iview的表格方式封装element中的table表格和分页_第1张图片

你可能感兴趣的:(技巧类,vue.js,elementui)