基于Element封装一个表格组件tableList的使用方法


Posted in Javascript onJune 29, 2020

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

内容:

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" style="width: 100%"
    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' ? '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' ? '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的使用方法

到此这篇关于基于Element封装一个表格组件tableList的使用方法的文章就介绍到这了,更多相关Element tableList内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
如何在Web页面上直接打开、编辑、创建Office文档
Mar 12 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 Javascript
javascript与jquery动态创建html元素示例
Jul 25 Javascript
关于vue.js弹窗组件的知识点总结
Sep 11 Javascript
javascript数据结构中栈的应用之符号平衡问题
Apr 11 Javascript
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
May 27 Javascript
angularJS利用ng-repeat遍历二维数组的实例代码
Jun 03 Javascript
jQuery 防止相同的事件快速重复触发方法
Feb 08 jQuery
浅谈layer弹出层按钮颜色修改方法
Sep 11 Javascript
浅谈vue项目用到的mock数据接口的两种方式
Oct 09 Javascript
原生js实现密码强度验证功能
Mar 18 Javascript
微信小程序反编译的实现
Dec 10 Javascript
iview实现图片上传功能
Jun 29 #Javascript
vue+animation实现翻页动画
Jun 29 #Javascript
vue+element实现图片上传及裁剪功能
Jun 29 #Javascript
vue实现匀速轮播效果
Jun 29 #Javascript
vant实现购物车功能
Jun 29 #Javascript
js实现随机点名器精简版
Jun 29 #Javascript
Node.js中出现未捕获异常的处理方法
Jun 29 #Javascript
You might like
Javascript中暂停功能的实现代码
2007/03/04 Javascript
JS 用6N±1法求素数 实例教程
2009/10/20 Javascript
js 蒙版进度条(结合图片)
2010/03/10 Javascript
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
在NodeJS中启用ECMAScript 6小结(windos以及Linux)
2014/07/15 NodeJs
extjs 分页使用jsp传递数据示例
2014/07/29 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
2016/08/05 Javascript
JS Select下拉框(支持输入模糊查询)
2017/02/04 Javascript
jquery animate动画持续运动的实例
2017/11/29 jQuery
vue中Npm run build 根据环境传递参数方法来打包不同域名
2018/03/29 Javascript
vue服务端渲染缓存应用详解
2018/09/12 Javascript
JS数据类型分类及常用判断方法
2020/11/19 Javascript
[43:49]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python中datetime常用时间处理方法
2015/06/15 Python
Python 描述符(Descriptor)入门
2016/11/20 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
python smtplib模块自动收发邮件功能(一)
2018/05/22 Python
numpy:np.newaxis 实现将行向量转换成列向量
2019/11/30 Python
python3 求约数的实例
2019/12/05 Python
python实现word文档批量转成自定义格式的excel文档的思路及实例代码
2020/02/21 Python
python函数enumerate,operator和Counter使用技巧实例小结
2020/02/22 Python
python和c语言哪个更适合初学者
2020/06/22 Python
Python2.x与3​​.x版本有哪些区别
2020/07/09 Python
python基于Kivy写一个图形桌面时钟程序
2021/01/28 Python
基于CSS3实现的黑色个性导航菜单效果
2015/09/14 HTML / CSS
css3实现画半圆弧线的示例代码
2017/11/06 HTML / CSS
携程英文网站:Trip.com
2017/02/07 全球购物
劳动之星获奖感言
2014/02/01 职场文书
推荐信格式范文
2014/05/09 职场文书
新闻工作者先进事迹
2014/05/26 职场文书
小学教师自我剖析材料
2014/09/29 职场文书
小学安全工作总结2015
2015/05/18 职场文书
Django migrate报错的解决方案
2021/05/20 Python
redis实现共同好友的思路详解
2021/05/26 Redis
pytorch 6 batch_train 批训练操作
2021/05/28 Python