Element封装tableList的方法

发布时间:2020-06-29 13:58:05 作者:清晨
来源:亿速云 阅读:226

这篇文章将为大家详细讲解有关Element封装tableList的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

我们项目中使用的表格一般都比较类似,如果不进行封装的话,那么每个页面都可能有一些类似的代码。不仅浪费时间,而且由于开发人员不同的开发习惯。后期维护人员需要花费一点时间去看每个人的代码。所以我直接将表格做一个二次封装,只要一个人去维护这份代码即可。下面是我封装的内容

内容:

1、支持直接传入后台请求地址渲染列表,且参数修改之后自动刷新
2、支持自定义每一列的显示
3、支持根据内容自动撑开列宽
4、支持动态筛选表头
5、支持分页
6、防抖
7、列权限
...
更多请自行尝试

以下是tableList 组件的代码

<template>
<!--刷新按钮 和 筛选列的多选框 layout中要有 control 才显示,默认显示-->
 <div class="table">
 <div class="table-control" v-if="layoutKey.control">
  <div class="table-control-title" @click="reload">
  <i class="el-icon-refresh"></i></div>
  <el-dropdown class="table-control-title">
  <span class="el-dropdown-link"><i class="el-icon-s-operation table-control-icon"></i></span>
  <el-dropdown-menu slot="dropdown" class="table-control-checkbox">
   <el-checkbox-group v-model="headItems" @change="changeChecked">
   <el-checkbox class="table-control-checkbox-item"
       v-for="(item,index) in allColumn"
       :label="item"
       :key="index">{{item}}
   </el-checkbox>
   </el-checkbox-group>
  </el-dropdown-menu>
  </el-dropdown>
 </div>
 <!--列表主体-->
 <el-table class="table" 
    ref="tableList"
    :data="tableData"
    :defaultSort.async="defaultSort"
    v-bind="$attrs"
    v-on="$listeners"
    @selectionChange="selectionChange"
    @sort-change="sortChange">
  <ex-table-column v-if="layoutKey.expand" type="expand" fixed>
  <slot name="expand" :data="props" slot-scope="props"/>
  </ex-table-column>
  <ex-table-column v-if="layoutKey.checkBox" fixed type="selection" :width="62"
      :selectable="selectable"/>
  <ex-table-column v-if="layoutKey.index" type="index" label="序号" width="60"/>
  <ex-table-column v-for="(column,index) in activeColumn" :key="index"
      :prop="column.field"
      :column-key="column.field" :label="column.title" :fixed="column.fixed"
      :sortable="column.sort" :selectable="column.selectable"
      :show-overflow-tooltip="column.tooltip"
      :autoFit='true' :width="column.width"
      :fitByClass="autoWidth(column.width)"
      :minWidth="column.minWidth || defaultWidth">
  <slot :name="column.field" :data="scope.row" :field="column.field" :content="column.field"
    :index="index" slot-scope="scope">
   <div>{{$utils.nvl(scope.row[column.field],'--')}}</div>
  </slot>
  </ex-table-column>
 </el-table>
 <!--分页控件,layout中要有 control 才显示,默认显示-->
 <el-pagination background small class="table-pagination"
     :current-page.sync="page.pageNo"
     :page-sizes="page.list"
     :page-size="page.pageSize"
     :layout="page.layout" :total="page.total"
     @current-change="handleCurrentChange"
     @size-change="handleSizeChange" v-if="layoutKey.page"/>
 </div>
</template>

<script>
 import debounce from 'lodash/debounce';
 import ExTableColumn from './ExTableColumn';

 export default {
 components: { ExTableColumn },
 // 提供出来给其他组件调用,具体用法参考 vue 官方用法
 provide() {
  return {
  tableList: this,
  };
 },

 props: {
 // 默认的表格大小
  defaultWidth: {
  type: Number,
  required: false,
  default: 100,
  },
 // 显示的控件,目前就page,control 两个可选,可根据需求自行扩展
  layout: {
  default: 'page,control',
  },
 // 多选时 返回的key,默认id
  checkKey: {
  type: [Number, String],
  default: () => 'id',
  },
 // 请求参数,必填
  req: {
  type: Object,
  required: true,
  default: () => ({
   url: undefined,
   type: 'post',
   params: {
   query: {},
   },
   pageNo: 1,
   pageSize: 1,
  }),
  },
 // 默认排序,参考 elementUI table 用法
  defaultSort: {
  type: [String, Object],
  required: false,
  },
  // 列表显示的列
  // {
   title : 必填 String,  显示的列名
   field : 必填 String ,  列中的key
   width : 选填,String  列宽,单位像素,
   fixed : 选填,String  是否固定的列,可选 right, left
   sort : 选填,Boolean  是否可排序
   expend: 选填,Boolean  是否可展开,配置slot:expand 显示展开内容
   limit :  选填,Boolean  权限控制,false 则不显示
  }
  columns: {
  type: Array,
  required: true,
  default: () => [{ title: '操作', field: 'ctrl', width: '60', fixed: 'right' }],
  },

 // 这一行的 CheckBox 是否可以勾选,用法参考elementUI table用法
  selectable: {
  type: Function,
  default: () => true,
  },
  
  // 其他table参数,都会传给table
 },
 data() {
  return {
  layoutKey: {},

  page: {
   list: [5, 10, 20, 50, 100],
   total: null,
   pageSize: 10,
   pageNo: 1,
   layout: 'total,sizes,prev,pager,next,jumper',
  },

  tableData: [],
  sort: '',
  checkRows: [],
  checkKeys: [],

  headItems: [],
  allColumn: [],
  activeColumn: [],
  };
 },

 methods: {
  sortChange({ prop, order }) {
  this.sort = `${prop} ${order === 'descending' &#63; 'desc' : 'asc'}`;
  this.refresh();
  },

  selectionChange(selection) {
  this.checkRows = selection;
  this.checkKeys = [];
  selection.map((row) => {
   this.checkKeys.push(row[this.checkKey]);
   return true;
  });
  this.$emit('selectionChange', selection);
  },

  /** **************************method*********************************** */

  // 分页
  async handleCurrentChange(currentPage) {
  this.page.pageNo = currentPage;
  this.$emit('handleCurrentChange', currentPage);
  await this.initTable({ vm: this });
  },

  handleSizeChange(size) {
  this.page.pageSize = size;
  this.page.pageNo = 1;
  this.$emit('handleSizeChange', size);
  this.initTable({ vm: this });
  },

  /** *****************************动态渲染头部************************************* */
  // 取消选中菜单
  changeChecked() {
  this.changeColumn({ vm: this });
  },
  changeColumn: debounce(async ({ vm }) => {
  const that = vm;
  const keys = new Set(vm.headItems);
  const activeColumn = vm.columns.filter((item) => {
   if (keys.has(item.title)) {
   return true;
   }
   return false;
  });
  that.activeColumn = activeColumn;
  that.activeColumn.splice(1, 0);
  }, 200),

  /** *****************************刷新************************************* */
  // 刷新表格数据(使用现有参数)
  refresh(type) {
  if (type === 'delete' && this.page.pageNo > 1 && this.tableData.length === 1) {
   this.page.pageNo = this.page.pageNo - 1;
  }
  this.initTable({ vm: this });
  },

  // 重新加载数据(重置到第一页)
  reload() {
  if (this.page.pageNo !== 1) {
   this.page.pageNo = 1;
  }
  this.initTable({ vm: this });
  },

  initTable: debounce(async ({ vm }) => {
  const that = vm;
  that.tableData = [];
  const params = that._.assign({
   pageNo: that.page.pageNo,
   pageSize: that.page.pageSize,
   sortStr: that.sort
  }, that.req.params); // 右值覆盖左值,返回左值
  // 发起请求,根据实际项目中,接口来做
  const { data } = await window.axios[that.req.type || 'post'](that.req.url, params);
  if (data && that.$utils.Type.isArray(data.result)) {
   that.tableData = data.result;
   that.page.total = data.total * 1;
  }
  that.$nextTick(() => {
   that.$emit('loadDone', that.tableData, params);
  });
  }, 300),

  getCheckRows() {
  return this.checkRows;
  },

  getCheckKeys() {
  return this.checkKeys;
  },

  handleHead(columns) {
  const allColumn = [];
  columns.map((item) => {
   if (!item.limit) {
   allColumn.push(item.title);
   }
   return true;
  });
  this.headItems = allColumn;
  this.allColumn = allColumn;
  this.changeChecked();
  },

  handleLayout() {
  const layout = this.layout;
  if (!layout) return null;
  layout.split(',')
  .map(
   (item) => {
   const key = item.trim();
   this.layoutKey[key] = true;
   return true;
   },
  );
  return this.layoutKey;
  },

  autoWidth(width) {
  if (this.$utils.isEmpty(width)) {
   return 'cell';
  }
  return width;
  },

  init() {
  this.handleLayout();
  this.handleHead(this.columns);
  if (this.defaultSort) {
   const { prop, order } = this.defaultSort;
   this.sort = `${prop} ${order === 'descending' &#63; 'desc' : 'asc'}`;
  }
  this.initTable({ vm: this });
  }
  ,
 },
 async created() {
  this.init();
 },

 watch: {
  queryParams: {
  handler() {
   this.reload({ vm: this });
  },
  },
  columns: {
  handler() {
   this.handleHead(this.columns);
  },
  },
 },
 computed: {
  queryParams() {
  if (this.$utils.isNotEmpty(this.req.params)) {
   return this.req.params;
  }
  return {};
  },
 },
 };
</script>

<style lang="less" scoped>
 @import './style/index';
</style>

使用方法

<template>
 <div>
 <table-list
  :req="tableReq"
  ref="tableList"
  :stripe="true" // table 原来的参数也是支持使用的,方法也支持使用。
  :columns="[
     {title:'用户名',field:'name',sort:'true',fixed:true},
     {title:'英文名',field:'aliasName',sort:'true',fixed:true},
     {title:'年龄',field:'age', sort:true},
     {title:'职业',field:'job', sort:true},
     {title:'邮箱',field:'email'},
     {title:'出生日期',field:'birthday'},
     {title:'家庭住址',field:'address'},
     {title:'户籍',field:'domicile'},
     ]">
  <!--格式化时间列,所有的列都可以这么使用,slot 名为列field-->
  <template slot="birthday" slot-scope="{data}">
  <span>{{format(data.birthday)}}</span>
  </template>
 </table-list>
 </div>
</template>

<script>
 import TableList from './table/components/TableList';

 export default {
 name: 'HelloWorld',
 components: { TableList },
 data() {
  return {
  tableReq: {
   url: '/user/list', //必填
   type: 'post', //可选, 默认 post
   params: {} // 可选
  }
  };
 },

 methods: {
  format(time) {
  if (this.$utils.isEmpty(time)) return '/';
  return this.$utils.format(new Date(time), 'yyyy-MM-dd HH:mm');
  },
 },

 mounted() {
 }
 };
</script>

关于Element封装tableList的方法就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

推荐阅读:
  1. 如何实现element-ui封装可搜索的懒加载tree组件
  2. vue element-ui之如何封装一个自己的组件

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

element tablelist lis

上一篇:修改DOClever的mongoDB数据库服务器IP地址

下一篇:iview如何实现图片上传功能

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》