elementUI+vue表格组件(支持多选、分页、选中回显、搜索、增删改)

功能

本组件能实现表格多选,分页,分页选中回显,新建、删除、修改、查询。

写在前,有问题欢迎问,有更好的建议欢迎留言~~~
使用时要注意将后台接口的情况,根据情况修改代码。
但是!!!!
不要只做复制粘贴,报错了就来乱喷的喷子

如果对你有帮助,希望你给我喜欢 !收藏!git上点星星!哈哈哈哈或哈哈哈哈(不要脸了)

实现效果

1.png
2.png
3.png

思路要点

将组件的操作产生的参数全部返回父组件,由父组件处理接口数据的交互
这样就可以提高表格组件的多样性,提高耦合程度,和高复用性,不必因为接口处理方式不同而重新编写组件。
比如点击确定按钮请求接口,不同的功能会调用不同接口地址,如果将接口请求都放入组件内,那么下次复用的时候就会改组件的代码。如果是多人维护,那大大增加的出bug的风险。

废话不多说,上代码

父组件

模板代码,主要是用tableData传输数据,其他@方法来接收参数

<template>
  <div>
    <checkboxTable
      :tableData="tableData" @Search="Search"
      @editline="editline" @deleteline="deleteline"
      @pageChange="pageChange" @createInfor="createInfor">
    </checkboxTable>
  </div>
</template>

引入组件

import checkboxTable from '@/components/common/checkboxTable'

数据结构和引用组件

   components: {
      checkboxTable
      //引用组件
    },
    data: () => ({
      //向table传值
      tableData: {
        //是否显示组件
        isShow: true,
        //是否显示新建弹框
        dialogTableVisible: false,
        //表格行项目列表和总条目数
        lineItems: {
          items: [],
          totalCount: 0,
        },
        //表格头部信息
        table: {
          header: {},
        },
        //存放搜索的key数组
        search: [],
        //分页器
        fenye: {
          pageIndex: 1,
          pageSize: 10,
        },
      },
    }),

将接收的数据进行处理,然后传入表格组件

     //处理表格数据
      dealTableData(obj) {
        //赋值列表
        this.tableData.lineItems = obj;
        //创建表头名称
        this.tableData.table.header = {
          "name": "姓名", "sex": "性别", "age": "年龄",
        };
        //搜索条件的key
        this.tableData.search = [
          {name: "姓名", id: "name", value: ""},
          {name: "年龄", id: "age", value: ""}];
      },

接收表格组件参数的示例函数,具体情况要根据后台接口来写

      //新建条目
      createInfor(details) {
        this.$post("新建接口", details, {
          emulateJSON: true
        }).then((response) => {
          if (response.code === 'success') {
            this.$message({message: '创建成功', type: 'success'});
            //请求成功后将弹窗关闭
            this.tableData.dialogTableVisible = false;
            //重新请求列表接口,刷新数据
            this.getTableData();
          } else {
            this.$message({message: '创建失败', type: 'warning'});
          }
        }, err => {
          console.log(err);
        });
      },
      //请求基础表格数据
      getTableData(msg) {
        this.$post("表格列表接口", {
          "page": this.tableData.fenye.pageIndex,
          "rows": this.tableData.fenye.pageSize
        }).then((response) => {
          console.log(response)
          if (response.code === 'success') {
            this.$message({message: response.msg, type: 'success'});
            //将数据传入处理函数
            this.dealTableData(response.data)
            return
          } else {
            this.$message({message: response.msg, type: 'warning'});
          }
        }, err => {
          console.log(err);
        });
      },

表格组件

没啥说的,代码注释里边都有。

哦,有一点要说
分页页码回显的时候,有时候不会重新渲染,所以要在分页器上加个v-if强制重新渲染
uuid这个插件,视项目情况引用

<template>
  <div>
    <div style="width:100%;">
      <div class=" clearfix" style="margin-bottom: 30px">
        <el-row>
          <el-col :span="6" v-for="(item,index) in tableData.search">
            <el-col :span="6" style="line-height: 40px;">{{item.name}}</el-col>
            <el-col :span="12">
              <el-input placeholder="" v-model=item.value
                        @keyup.enter.native="Search()"></el-input>
            </el-col>
          </el-col>
          <el-col :span="8">
            <el-button @click="Search()">查询</el-button>
            <el-button  type="primary" @click="createInfor()"> 新建</el-button>
            <el-button  type="danger" round @click="batchDelete()"> 批量删除</el-button>

          </el-col>
        </el-row>
      </div>

      <!--引用表格-->
      <el-table
        ref="singleTable" border
        :row-key="getRowKeys"
        stripe
        :height=(this.$store.state.bodyHeight-150)
        :reserve-selection="true"
        :data="tableData.lineItems.items"
        @selection-change="handleCurrentChange"
        style="width: 100%">
        <!--多选  prop要填唯一标识-->
        <el-table-column label="选择" :reserve-selection="true" prop="uuid" width="32px" type="selection">
        </el-table-column>
        <!--循环输出表头-->
        <el-table-column v-if="key!='id'" :label="value" :render-header="labelHeadFit"
                         v-for="(value, key) in tableData.table.header"
                         :key="value">
          <!--循环输出对应value-->
          <template slot-scope="scope">
            <span>{{scope.row[key]}}</span>
          </template>
        </el-table-column>
        <!--定义操作功能-->
        <el-table-column width="150px" label="操作">
          <template slot-scope="scope">
                        <span>
                          <el-button type="primary " size="mini" plain @click="editline(scope.row)">修改</el-button>
                          <el-button type="danger " size="mini" plain @click="deleteline(scope.row)">删除</el-button>
                            </span>
          </template>
        </el-table-column>
      </el-table>
    </div>


    <!--分页器-->
    <el-pagination
      @current-change="pageChange" v-if="tableData.isShow"
      :current-page="tableData.pageIndex"
      :page-size=tableData.fenye.pageSize
      layout="total, prev, pager, next, jumper"
      :total=tableData.lineItems.totalCount>
    </el-pagination>
    <!--新建条目的弹框-->
    <el-dialog title="信息" :visible.sync="tableData.dialogTableVisible">
      <el-form :model="form" class="inputWidth" ref="form">
        <el-form-item label="姓名" :label-width="formLabelWidth" prop="name"
                      :rules="[
      { required: true, message: '姓名不能为空',trigger: 'blur' },
    ]">
          <el-input v-model="form.name" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="性别" :label-width="formLabelWidth" prop="sex"
                      :rules="[
      { required: true, message: '请选择性别',trigger: 'change' },
    ]">
          <el-select v-model="form.sex" placeholder="请选择性别">
            <el-option label="男" value="男"></el-option>
            <el-option label="女" value="女"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="年龄" :label-width="formLabelWidth" prop="age"
                      :rules="[
      { required: true, message: '年龄不能为空'},
      { type: 'number', message: '年龄必须为数字值'}
    ]">
          <el-input type="age" v-model.number="form.age" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="tableData.dialogTableVisible = false">取 消</el-button>
        <el-button type="primary" @click="submit('form')">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
  //生成uuid唯一标识,可以不引用
  import UUID from 'node-uuid';

  export default {
    //接收父组件传来的数据
    props: {
      tableData: Object,
    },
    data() {
      return {
        //控制label的宽度
        formLabelWidth: '80px',
        //记录是修改还是新建
        type: "",
        form: {
          //唯一标识
          uuid: "",
          name: '',
          sex: '',
          age: '',
        },
        // 获取row的key值
        getRowKeys(row) {
          return row.uuid;
        },
        //存放分页选中条目,回显用
        selectedData: [],
        //存放选中条目,做传参用
        templateRadio: [],
      }
    },
    mounted() {
    },
    methods: {
      //确定选中
      handleCurrentChange(rows) {
        console.log(rows);
        //将选中赋值到回显和传参数组
        this.templateRadio = rows;
        this.selectedData = [];
        if (rows) {
          rows.forEach(row => {
            if (row) {
              this.selectedData.push(row.uuid);
            }
          });
        }
      },
      //表头自适应
      labelHeadFit(h, {column, index}) {
        let l = column.label.length
        let f = 16 //每个字大小,其实是每个字的比例值,大概会比字体大小差不多大一点,
        column.minWidth = f * l //字大小乘个数即长度 ,注意不要加px像素,这里minWidth只是一个比例值,不是真正的长度
        //然后将列标题放在一个div块中,注意块的宽度一定要100%,否则表格显示不完全
        return h('div', {class: 'table-head', style: {width: '100%'}}, [column.label])
      },
      //行项目分页
      pageChange(val) {
        //将页码传回父组件
        this.$emit("pageChange", val);
      },
      //新建行项目
      createInfor() {
        //生成uuid
        this.form.uuid = UUID.v1();
        //打开新建弹窗
        this.tableData.dialogTableVisible = true;
        //标识为新建
        this.type = "createInfor"
      },
      //修改行项目
      editline(details) {
        //赋值详情做展示用
        this.form = details
        this.tableData.dialogTableVisible = true;
        //标识为修改
        this.type = "editline"
      },
      //删除有行项目
      deleteline(details) {
        this.$emit("deleteline", details);
      },
      //批量删除
      batchDelete(){
        this.$emit("batchDelete", this.templateRadio);
      },
      //查询
      Search() {
        //将查询的value传回
        this.$emit("Search",this.tableData.search);
      },
      //提交时统一分发
      submit(formName) {
        console.log(formName, this.form)
        this.$refs[formName].validate((valid) => {
          if (valid) {
            switch (this.type) {
              //修改行项目
              case "editline":
                this.$emit("editline", this.form);
                break;
              //创建行项目
              case "createInfor":
                this.$emit("createInfor", this.form);
                break;
            }
          } else {
            console.log('error submit!!');
            return false;
          }
        });

      }
    }
  }
</script>


完整插件git地址,有帮助到你,就给我个星星哟~~
https://github.com/zccone/-plug-in-checkBoxTable

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 几年前,命运把我和西藏紧紧联系在一起。当第一次以主人翁的姿态走进雪域高原这片神奇土地的时候,高原纯美的风景和生活在...
    触动的心灵阅读 1,580评论 0 4
  • 饮酒 魏晋 · 陶渊明 结庐在人境,而无车马喧。 问君何能尔?心远地自偏。 采菊东篱下,悠然见南山。 山气日夕佳,...
    SeanQD阅读 349评论 0 0
  • 莫嗟岁月太匆匆,喜看花蕊迎新春。 漫漫征途岂迷向,滔滔鄱水总流东。 坎坷难把初心改,名利焉将傲骨融。 携手激情更奋...
    逸塵居士阅读 486评论 0 0