基于element-ui与vue结合带有编辑、删除、搜索、添加功能的表格与分页的静态页面

这是一个基于element-ui与vue结合带有增删改查的静态功能(不与后端交互,实际上,如果与后端进行交互的话,逻辑会更加的简单,减少了许多没必要的考虑)的表格与分页相结合的一个demo,里面有详细的做法流程与解析,可供各位参考。下面可以看下效果图

                        demo界面图

基于element-ui与vue结合带有编辑、删除、搜索、添加功能的表格与分页的静态页面
多选择框共同查询
基于element-ui与vue结合带有编辑、删除、搜索、添加功能的表格与分页的静态页面

写这个的目的是,element-ui的表格并不能满足个人的需求,估计这种情况许多人都遇到,所以就写了这个小demo,来记录下自己的思路,并且希望这个demo能给其他前端爱好者或者从业者一个小小的参考,下面是完整的代码,直接复制粘贴就可以使用了,也可以根据的需求进行给改。

<template> 
    <el-container id="content">
      <el-header>
        <el-row>
          <el-col :span="10">
            <el-button type="danger" @click="delAll" style="float: left"
              >删除人员</el-button
            >
            <el-popover
            v-model="visible"
              placement="right"
              width="400"
              trigger="click"
              :open-delay="200"
              :close-delay="200"
            >
              <el-form
                :model="validateForm"
                ref="validateForm"
                label-width="100px"
                class="demo-ruleForm"
              >
                <el-form-item
                  label="年龄"
                  prop="age"
                  :rules="[{ required: true, message: '年龄不能为空' }]"
                >
                  <el-input
                    type="age"
                    v-model="validateForm.age"
                    autocomplete="off"
                  ></el-input>
                </el-form-item>
                 <el-form-item
                  label="名称"
                  prop="name"
                  :rules="[{ required: true, message: '姓名不能为空' }]"
                >
                  <el-input
                    type="name"
                    v-model="validateForm.name"
                    autocomplete="off"
                  ></el-input>
                </el-form-item>
                <el-form-item>
                  <el-button type="primary" @click="submitForm('validateForm')"
                    >提交</el-button
                  >
                  <el-button @click="resetForm('validateForm')">重置</el-button>
                </el-form-item>
              </el-form>
              <el-button slot="reference" type="primary" style="margin-left:20px">添加人员</el-button>
            </el-popover>
          </el-col>
          <el-col :span="6">
            <el-input
              clearable
              v-model="searchInput.age"
              placeholder="请输入年龄搜索"
              @input="searchCommon"
            ></el-input>
          </el-col>
          <el-col :span="6">
            <el-input
              clearable
              v-model="searchInput.name"
              placeholder="请输入名字搜索"
              @input="searchCommon"
            ></el-input>
          </el-col>
        </el-row>
      </el-header>
      <el-main>
        <el-table
          :data="tableData.slice((this.currentPage-1)*this.pageSize,this.currentPage*this.pageSize)"
          style="width: 100%"
          stripe
          @selection-change="handleSelectionChange"
        >
          <el-table-column type="selection" width="55"> </el-table-column>

          <el-table-column label="年龄" prop="age">
            <template slot-scope="scope">
              <el-input v-if="scope.row.editable" v-model="scope.row.age" @input="inputCodeRow(scope.$index, scope.row)">{{
                scope.row.age
              }}</el-input>
              <span v-else
                >{{ scope.row.age }}
              </span>
            </template>
          </el-table-column>

          <el-table-column label="名字" prop="name">
            <template slot-scope="scope">
              <el-input v-if="scope.row.editable" v-model="scope.row.name" @input="inputCodeRow(scope.$index, scope.row)">{{
                scope.row.name
              }}</el-input>
              <span  v-else
                >{{ scope.row.name }}
              </span>
            </template>
          </el-table-column>

         
          <el-table-column align="right" label="操作">
            <template slot-scope="scope">
               <span v-if="scope.row.editable">
                <el-button
                  :disabled='empty'
                  size="mini"
                  @click="handleSave(scope.$index, scope.row)"
                  >保存</el-button
                >
                <el-button
                  size="mini"
                  @click="handleCancel(scope.$index, scope.row)"
                  >取消</el-button
                >
              </span>
              <span v-else>
                <el-button
                  :disabled='forbid'
                  size="mini"
                  @click="handleEdit(scope.$index, scope.row)"
                  >编辑</el-button
                >
              </span> 
              <el-button
                v-show="!scope.row.editable"
                size="mini"
                type="danger"
                @click="handleDelete(scope.$index, scope.row)"
                >删除</el-button
              >
            </template>
          </el-table-column>
        </el-table>
        <template>
          <el-pagination
            @current-change="handleCurrentChange"
            @size-change="handleSizeChange"
            :current-page.sync="currentPage"
            :page-sizes="[5, 10, 15, 20]"
            :page-size="pageSize"
            layout="total,sizes,prev, pager, next, jumper"
            :total="tableData.length"
          >
          </el-pagination>
        </template>
      </el-main>
    </el-container>

</template>  

<script>

export default {
  name: "History",
  components: {

  },
  data() {
    return {
      //原始专案代码
      searchInput: {
        //年龄输入框
        age: "",
        //名字输入框
        name: "",
        //名字输入框
      },
      //点击编辑按钮时,如果取消编辑,对信息进行备份还原
      originalAge:"0",
      originalName:'',
      //分页数据相关
      currentPage: 1,
      pageSize: 5,
      //备份数据表格,用于搜索完记录后,还原数据,只有删除才需要重新备份,因此在created或者mounted声生命周期函数深拷贝
      originalData: [],
      //表格数据相关
      tableData: [
        {
          id:100,
          age:"20",
          name:'李四',
          editable:false,
        },
        {
          id:101,
          age:"20",
          name:'张三',
          editable:false,
        },
        {
          id:102,
          age:"20",
          name:'王五',
          editable:false,
        },
        {
          id:103,
          age:"18",
          name:'张三',
          editable:false,
        },
        {
          id:104,
          age:"10",
          name:'小陈',
          editable:false,
        },
        {
          id:105,
          age:"20",
          name:'小陈',
          editable:false,
        },
        {
          id:106,
          age:"25",
          name:'小丽',
          editable:false,
        },
        {
          id:107,
          age:"20",
          name:'张三',
          editable:false,
        },
        {
          id:108,
          age:"21",
          name:'张三',
          editable:false,
        },
        {
          id:109,
          age:"30",
          name:'张三',
          editable:false,
        },
        {
          id:110,
          age:"45",
          name:'麻子',
          editable:false,
        },
        {
          id:111,
          age:"40",
          name:'狗二蛋',
          editable:false,
        }],
      //选择框
      multipleSelection: [],
      //禁止状态,确保只有一个编辑按钮可点,当一个编辑按钮点亮后,其他编辑不可点
      forbid: false,
      //保存状态,内容为空禁止保存
      empty: false,
      //记录一个静态数据的最后一个id,为后续添加表格数据时,添加的id在此id的基础上进行相加
      addId:111, 
      //信息表单
      validateForm: {
        age: "",
        name:""
      },
      //表单显示状态
      visible:false
    };
  },
  methods: {
    //人员单个删除
    handleDelete(index, row) {
     //获取要删除的id,row是element-ui封装好的点击的时候能获取你点击那一行的信息
      var delId = row.id
      this.$confirm("此操作将永久删除该文件, 是否继续?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
          //遍历表格,筛选掉表格中符合要删除的id,而不符合的返回给table,达到删除的目的
           this.tableData = this.tableData.filter(ele => 
            ele["id"] != delId //或者可以写成ele.id != delId
          ) 
          //需要将最新的表格数据传递给备份记录,这一步操作是解决搜索完东西后,表格的还原
           this.originalData = JSON.parse(JSON.stringify(this.tableData))
            this.$message({
              type: "success",
              message: "删除成功!",
            })
          })  
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    //人员批量删除
    delAll() {
      //没有点击选择框,点击删除直接提示
      if (this.multipleSelection.length == 0) {
        this.$alert("选择框未选择,点击删除按钮无效", "警告", {
          confirmButtonText: "确定",
          callback: () => {
            this.$message({
              type: "info",
              message: `删除失败`,
            });
          },
        });
        return;
      }
      this.$confirm("此操作将永久删除被选中的文件, 是否继续?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        //遍历出所有选中的id,然后将表格数据中的id与选中的id做匹配,符合的删除
        for(let key in this.multipleSelection){ //这里涉及到for(变量 in  数组) for(变量 of 对象 )
       //for(变量 in 对象)    for(变量 of 对象)  变量具体指的是什么了。需要好好去了解一下
          //更新表格数据,将删除信息的表格重新赋值
          this.tableData = this.tableData.filter(ele=>
          this.multipleSelection[key].id !=ele.id
          )
        }
        //这里涉及深度拷贝知识,有不懂的可以查一下深度拷贝,浅拷贝,以及直接赋值的异同
        this.originalData = JSON.parse(JSON.stringify(this.tableData))
            this.$message({
              type: "success",
              message: "删除成功!",
            })
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消删除",
            });
          });
    },

    //搜索函数,该函数能在前一个搜索的基础上进行二次搜索,可以自定义多个搜索,在此函数的基础上添加即可
      searchCommon() {
        this.forbid = false
      this.tableData = JSON.parse(JSON.stringify(this.originalData))
      //搜索出的数据
      var searchList = []
      for(var key in this.searchInput){
        /*这里有一点需要主要的是,this.tableDate内每一个对象的id健值还有name健值
        跟输入框的this.searchInput内的age和name同名 所有才可以直接用for(var key in this.searchInput)中的key否则不可以*/
        if(this.searchInput[key] != ""){ //遍历所有搜索框,如果某一项搜索框为空,直接跳过这个搜索框
           searchList = this.tableData.filter(ele=>  {
             ele.editable = false
      // 忽略大小写匹配ele[key].toLowerCase().indexOf(this.searchInput[key].toLowerCase() != -1),
      // 但是对于数字而言没有任何效果,toLowerCase()只支持字符串  不支持数字类型 如果想匹配数字的话可以将数字变成字符串的数字 例如 1 => '1'
      // 此外indexOf() 也是来匹配字符串而非其他类型,否则报错   
        return  ele[key].toLowerCase().indexOf(this.searchInput[key].toLowerCase()) >-1  //注意这里的xxx.indexOf(xxx) >-1,而不是xxx.indexOf(xx >-1) 不要括错位置了,否则出问题
          })
        }
        else{
        /* 这一步其实也并不完善,如果遇到了四个搜入框,1.3输入框内容为空,2.4输入框有内容,
        那么会导致当遇到第三个输入框为空的情况下,将第二次输入框筛选出的东西给还原成数据表格元素模样
        所以可以多选择添加一个表格,来记录被搜索框搜索出的东西,如果这么提示还不能理解的话,到时候我写出来
        或者做一层判断只有searchList不为空才进行第368行否则不进行,就可以解决完上面说的问题*/
          searchList =JSON.parse(JSON.stringify(this.tableData))
        }
        //将第一次过滤出的信息保留,留着下一次搜索框内容过滤,直到搜索框没有内容
        this.tableData = JSON.parse(JSON.stringify(searchList))
      }
      //搜索框内容都为空那么allEmpty = true
      var allEmpty = true
      for(let key in this.searchInput){
        if(this.searchInput[key]!=''){
          //如果任意输入框存在一个为空的内容,那么allEmpty = false
           allEmpty = false
        }
      }
      //搜索内容都为空,通过备份的数据表格还原表格数据
      if(allEmpty){
      this.tableData = JSON.parse(JSON.stringify(this.originalData))
      this.tableData.forEach(e=>{
      e.editable  = false
    })
        return this.tableData
      }
    },
    /*编辑函数 */
    handleEdit(index, row) {
      console.log(row)
      //这一步操作是确保只有一个编辑按钮可点,当点击了其中一个编辑按钮,其他编辑按钮应该不可点
      this.forbid = true
      //基础点击前的名字和年龄,如何用户点取消时还原数据
      this.originalAge = row.age
      this.originalName = row.name
      row.editable = true;
      if(row.age !='' && row.name!=''){ //只要俩个内容不为空,那么就可以点击保存按钮
        this.empty = false //这一步操作是解决当某一项输入框为空,再点击取消,再点击编辑时,保存按钮不给保存的情况
      }
    },
    //编辑函数取消按钮
    handleCancel(index, row){
        this.$confirm("是否要取消编辑?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.forbid = false
          row.age = this.originalAge
          row.name = this.originalName 
          row.editable = false;
          this.$message({
            type: "success",
            message: "取消编辑成功!",
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消编辑",
          });
        });   
    },
    //编辑内容为空时,不给保存
    inputCodeRow(index,row){
     if(row.age == '' || row.name == ''){
         this.empty = true //为空的时候,保存按钮不可点击
     }else{
         this.empty = false
     }
    },
    //编辑函数保存按钮
    handleSave(index, row){
        //输入框跟原来输入框内容一致时,不做任何操作,
       //当改变了表格,那么就将备份的数据表格记录成最新的状态防止搜索的时候以旧的表格做为模板进行搜索
          this.originalData = JSON.parse(JSON.stringify(this.tableData))
          row.editable = false
          this.forbid = false
          return        
    },
   
    //添加人员
   submitForm(formName) {
         this.visible = true
        this.$refs[formName].validate((valid) => {
          if (valid) {
            this.addId +=1
            this.validateForm.id = this.addId,
            this.validateForm.editable = false,
            this.tableData.push(JSON.parse(JSON.stringify(this.validateForm)))
            //添加完人员,将最新表格数据记录一份
            this.originalData = JSON.parse(JSON.stringify(this.tableData))
            //每次添加完后都重置一下表单
            this.$refs[formName].resetFields();
            this.visible = false
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      },
      
    //当前页数改变
    handleCurrentChange(val) {
      this.currentPage = val;
     
    },
    //页面展示的数据发生改变
    handleSizeChange(val) {
      this.pageSize = val;
     
    },
    //多选选择框
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
  },

  mounted() {
     this.originalData = JSON.parse(JSON.stringify(this.tableData))
  },
 
};
</script>

<style scoped>
html,
body,
.el-container {
  /*设置内部填充为0,几个布局元素之间没有间距*/
  padding: 0px !important;
  /*外部间距也是如此设置*/
  margin: 0px !important;
  /*统一设置高度为100%*/
  height: 100vh;
}
#content {
  min-width: 900px;
}
#content .el-header {
  margin-top: 20px;
  line-height: 60px;
}
#content .el-header .el-button {
  margin-top: 10px;
  width: 100px;
}
.el-row .el-col {
  margin-left: 20px;
}
.el-pagination {
  position: relative;
  bottom: 0;
  height: 60px;
  line-height: 60px;
  text-align: center;
  padding: 15px 5px 0;
}
</style>

最后感谢大家的观看,如果对你们有一点小小的帮助,我都会感到开心,毕竟分享最光荣。有任何错误的话都欢迎各位在评论区中指出,此外需要转载的话,麻烦标记一下出处,毕竟也是我的劳动成果。谢谢!

上一篇:数据分析进阶-Excel自动化工具包openpyxl的基础使用


下一篇:MySQL5.7_恢复数据_ibd文件恢复表