# 表格的添加删除

<template>
  <div>
    <div class="form">
      编号: <input type="text" v-model="formData.id">
      名称: <input type="text" v-model="formData.name">

      <button @click="addData">添加</button>
      搜索:<input type="text" v-model="keywords">
    </div>

    <table class="table">
      <th>编号</th>
      <th>名称</th>
      <th>创建时间</th>
      <th>操作</th>
      <tr v-show="list.length==0">
        <td colspan="4">列表无数据</td>
      </tr>

      <tr v-for="item in search(keywords)" :key="item.id">
        <td>{{item.id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.ctime}}</td>
        <!--绑定delete事件,根据括号里的参数进行删除-->
        <td>
          <a href="#" @click="delData(item.id)">删除</a>
        </td>
      </tr>
    </table>
  </div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export default {
  name: 'table1',
  data() {
    return {
      list: [{ id: 1, name: '前端', ctime: new Date() },
        { id: 2, name: 'java', ctime: new Date() }],
      // 用户添加的数据
      formData: {
        id: '',
        name: '',
      },
      keywords: '',
    };
  },
  methods: {
    addData() {
      // 将数据追加到list中
      const p = { id: this.formData.id, name: this.formData.name, ctime: new Date() };
      this.list.push(p);
      // 清空页面上的文本框中的数据
      this.formData.id = '';
      this.formData.name = '';
    },
    delData(id) {
      // 0 提醒用户是否要删除数据
      if (!confirm('是否要删除数据?')) {
        // 当用户点击的取消按钮的时候,应该阻断这个方法中的后面代码的继续执行
        return;
      }
      // 1 调用list.findIndex()方法根据传入的id获取到这个要删除数据的索引值
      const index = this.list.findIndex(item => item.id == id);
      // 2 调用方法:list.splice(待删除的索引, 删除的元素个数)
      this.list.splice(index, 1);
    },

    search(keywords) { // 根据关键字,进行数据的搜索,返回匹配的item
      const newList = this.list.filter((item) => {
        if (item.name.includes(keywords)) {
          return item;
        }
      });

      return newList;
    },
  },
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  .table {
    width: 800px;
    margin: 20px auto;
    border-collapse: collapse;  /*这一行,不能少:表格的两边框合并为一条*/
  }

  .table th {
    background: #0094ff;
    color: white;
    font-size: 16px;
    border: 1px solid black;
    padding: 5px;
  }

  .table tr td {
    text-align: center;
    font-size: 16px;
    padding: 5px;
    border: 1px solid black;
  }

  .form {
    width: 800px;
    margin: 20px auto;
  }

  .form button {
    margin-left: 10px;
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# element ui 上传excel表格

自定义上传方法 (opens new window)

  <el-upload
       ref="upload"
       class="upload-demo"
       :action="api"
       :on-change="fileChange"
       :headers="headers"
       :auto-upload="false"
       :limit="1"
       :file-list="fileList"
       :on-error="handleError"
       :on-success="handleSuccess"
       :on-preview="handlePreview"
       :on-remove="handleRemove"
       :on-exceed="handleExceed"
       accept=".xls,.xlsx">
       <el-button size="small" type="success" slot="trigger">导入</el-button>
            <el-button style="margin-left: 10px;" size="small" type="primary" @click="submitUpload">上传</el-button>
           <div slot="tip" class="el-upload__tip" style="display: inline-block;margin-left: 10px;color:red">注意:只能上传.xlsx /.xls文件</div>
  </el-upload>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ata(){
       return{
           api:window.SITE_CONFIG.baseUrl + 'store/upload',  //请求的接口地址
          headers: { 'token': window.localStorage.getItem('token') } //携带的头部信息
       }
   }
   
   methods:{
    // 选择文件
    fileChange (file, fileList) {
      this.fileList = fileList
      const isexcle = file.raw.type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.raw.type == 'application/vnd.ms-excel'
      if (!isexcle) {
        this.$message.error('请选择 .xlsx /.xls文件')
        this.$refs.upload.clearFiles()
        return false
      }
    },
    // 上传
    submitUpload () {
      if (this.fileList.length <= 0) {
        this.$message.error('请选择需要上传的文件')
        return false
      }
      this.$refs.upload.submit()
    },
    // 删除文件
    handleRemove (file, fileList) {
      this.fileList = fileList
    },
   // 预览
    handlePreview (file) {
     
    },

    // 上传成功
    handleSuccess (response, file, fileList) {
      this.$refs.upload.clearFiles()
      if (response.code == 0) {
        this.$message.success('上传成功!')
      } else {
        this.$message.error('上传失败,请重新上传')
      }
    },
    // 上传失败
    handleError (err, file, fileList) {
      this.$refs.upload.clearFiles()
      this.$message.error('上传失败,请重新上传')
    },
    // 超过限制
    handleExceed (file, fileList) {
      this.$message.error('一次只能上传一个文件')
    },
      }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 下载excel表格

  • 把excel表格放在public/template/factorycost.xlsx中
download () {
      window.location.href = './template/factorycost.xlsx'
    }
1
2
3

# 导出excel表格

  1. 后台返回的是数据
安装插件
npm install xlsx file-saver -S
npm install script-loader -S -D
1
2
3
在src目录下新建文件夹vendor,放入2个文件Export2Excel.js和Export2Zip.js    //见代码块/文件/vendor

<button @click="handleDownload">导出</button>

//data数据
list: [
        {
          id: 1001,
          name: '啦啦啦啦啦啦阿拉啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦',
          dep: '信息中心',
          emp: 'ddd',
        },
      ],
      
methods:{
     handleDownload() {
      import('../vendor/Export2Excel').then((res) => {
        const tHeader = ['id', '名称', '部门', '管理人'];  //表格表头
        const filterVal = ['id', 'name', 'dep', 'emp']; //数据的字段
        const list = this.list;
        const data = this.formatJson(filterVal, list);
        res.export_json_to_excel({
          header: tHeader,
          data,
          filename: '店铺信息表',   //文件名
          autoWidth: true,   //列宽自动
          bookType: 'xlsx',  //文件类型
        });
      });
    },
    formatJson(filterVal, jsonData) {
      return jsonData.map(v => filterVal.map((j) => {
        if (j === 'timestamp') {
          return parseTime(v[j]);
        }
        return v[j];
      }));
    },
      }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
安装插件
npm install -S file-saver xlsx
npm install -D script-loader
1
2
3
在src目录下新建文件夹vendor,放入2个文件  Export2Excel.js 和 Blob.js   //见代码块/文件/vendor2

更改 Export2Excel.js中的引入文件为
require('script-loader!file-saver');
require('script-loader!@/vendor/Blob');
require('script-loader!xlsx/dist/xlsx.core.min');

  <el-button size="small" type="success" @click="exportExcel">导出</el-button>
  
  async  exportExcel () {
      var res = await this.$api.get('store/exportExcel')

      // excel数据导出
      require.ensure([], () => {
        const {
          export_json_to_excel
        } = require('../../vendor/Export2Excel')
        const tHeader = ['店铺编号', '店铺名称', '部门', '管理人']  //表头
        const filterVal = ['storeId', 'storeName', 'department', 'empName']  //数据库字段
        const list = res.data.data
        const data = this.formatJson(filterVal, list)
        export_json_to_excel(tHeader, data, '店铺信息')
      })
    },
    formatJson (filterVal, jsonData) {
      console.log(jsonData)
      return jsonData.map(v => filterVal.map(j => v[j]))
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  1. 后台返回文件流
    vue中使用axios处理post方法导出excel表格 (opens new window)
export function exportExcels (data) {
  return request({
    url: 'rs/repairOrder/export',
    method: 'post',
    responseType: 'blob',  //重点
    data
  })
}

//请求成功后返回的结果
 .then((res) => {
          const blob = new Blob([res])
          const fileName = '订单列表.xlsx'
          const elink = document.createElement('a')
          elink.download = fileName
          elink.style.display = 'none'
          elink.href = URL.createObjectURL(blob)
          document.body.appendChild(elink)
          elink.click()
          URL.revokeObjectURL(elink.href) // 释放URL 对象
          document.body.removeChild(elink)
        })
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 表格分页点击下一页保留前一页的数据

<el-table-column
     type="selection"
      width="55"
      :reserve-selection="true">
 </el-table-column>
1
2
3
4
5
 :row-key="getTaskRowKeys"   //table属性
  // 返回id设置row-key
      getTaskRowKeys (row) {
        return row.id
      }
1
2
3
4
5

# 表格默认选中

<el-table
     @row-click="roleRowClick">
  <el-table-column
       type="selection"
       width="55"
      :reserve-selection="true"
    ></el-table-column>
</el-table>
1
2
3
4
5
6
7
8
 data(){
      return{
        getRoleRowKeys (row) {
          return row.id
      }
      }
1
2
3
4
5
6
  watch: {
    roleList: function () {  //监听列表
      this.roleList.forEach((item, i) => {
        this.selectRole.forEach((m, n) => {  //选中的角色
          if (item.id == m.id) {
            this.$nextTick(() => {
              this.$refs.role.toggleRowSelection(item, true)
            })
          }
        })
      })
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
watch:{
   areaChecked() {
       this.$nextTick(() => {
         this.areaList.forEach((item, index) => {
           if (item.isChecked) {
             this.$refs.areaTable.toggleRowSelection(item, true)
           } else {
             this.$refs.areaTable.toggleRowSelection(item, false)
           }
         })
       })
     },
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 分页功能序号自动增加

indexMethod(index) {
        return this.pageSize*(this.pageNumber-1)+index+1
    }
1
2
3

# 要对后台返回数组进行增加/删除/默认选中操作

  • //scr/function/public.js
//判断数组中有没有这个id存在(可传一维数组和二维数组)
//如果是店铺使用的传的是 店仓号 storeno
export function isArrayCZ(idArr, array, type) {
  if (typeof idArr == 'object' || typeof idArr == 'array') {
    if (array.length == 0) return false
    if (idArr.length > array.length) return false
    array.forEach((item) => {
      idArr.forEach((m, n) => {
        if (m[type] != item[type]) {
          return false
        }
      })
    })
    return true
  } else {
    let check = false
    array.forEach((item) => {
      //说明为一维
      if (item[type] == undefined) {
        if (idArr == item)
          return check = true
      } else {
        if (idArr == item[type])
          return check = true
      }
    })
    return check
  }
}

//删除对应数组中对应id的数据
export function deleteArr(idArr, arr, type) {
  if (typeof idArr == 'object' || typeof idArr == 'object') {
    arr.forEach((item, index) => {
      idArr.forEach((m, n) => {
        if (m[type] == item[type]) arr.splice(index, 1)
      })
    })
  } else {
    arr.forEach((item, index) => {
      if (item[type] == undefined) {
        if (idArr == item) arr.splice(index, 1)
      } else {
        if (idArr == item[type]) arr.splice(index, 1)
      }
    })
  }
  return arr
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  • //src/function/selectMethods.js
import { isArrayCZ, deleteArr } from '@/function/public'
// 可传入type=id/storeNo/其他
// arr表示当前页得变化得数组
// selectArr为最终选择得数组
// tableRefs为表单得注册
export default {
  // 多选框(二维数组)
  selectionChange(select, arr, selectArr, type, category) {
    arr = select
    select.forEach((item) => {
      const isArea = isArrayCZ(item[type], selectArr, type)
      if (!isArea) {
        // 若为一维数组
        if (category == 1) {
          selectArr.push(item[type])
        } else {
          selectArr.push(item)
        }
      }
    })
  },
  // 单击行选中
  rowClick(row, arr, selectArr, tableRefs, type) {
    arr.forEach((item) => {
      if (item[type] == row[type]) {
        selectArr = deleteArr(item[type], selectArr, type)
      }
    })
    tableRefs.toggleRowSelection(row)
  },
  // 点击勾选项
  checkedSelect(selection, row, arr, selectArr, type) {
    const isArea = isArrayCZ(row[type], selectArr, type)
    const isTwo = isArrayCZ(row[type], arr, type)
    if (isArea && !isTwo) {
      selectArr = deleteArr(row[type], selectArr, type)
    }
  },
  //  全选
  selectAll(selection, tableData, selectArr, type, category) {
    const role = isArrayCZ(tableData, selection, type)
    console.log(role)
    if (role) {
      selection.forEach((item) => {
        const isRole = isArrayCZ(item[type], selectArr, type)
        if (!isRole) {
          if (category == 1) {
            // 添加一维数组
            selectArr.push(item[type])
          } else {
            // 添加对象
            selectArr.push(item)
          }
        }
      })
    } else {
      tableData.forEach((m, n) => {
        const isRole = isArrayCZ(m[type], selectArr, type)
        if (isRole) {
          selectArr = deleteArr(m[type], selectArr, type)
        }
      })
    }
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  • //src/main.js
import selectMethods from '@/function/selectMethods'
 Vue.prototype.$select = selectMethods
1
2
  • //index.vue
     <el-table
        ref="storeTable"
        :data="storeList"
        :row-key="getStoreRowKey"
        @select="storeCheckedSelect"
        @row-click="storeRowClick"
        @selection-change="storeSelectionChange"
        @select-all="storeSelectAll"
      >
        <el-table-column
          align="center"
          type="selection"
          width="55"
          :reserve-selection="true"
        />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data(){
  return{
   getAreaRowKeys(row) {
        return row.id
   }
 }
}


//methods
   // store 点击勾选项
    storeCheckedSelect(selection, row) {
      this.selectStoreArr = selection // 当前页选中的数据
      this.$select.checkedSelect(selection, row, this.selectStoreArr, this.agencyInfo.store_object, 'id')
    },
     
     // store 多选框
    storeSelectionChange(select) {
      this.selectStoreArr = select
      this.$select.selectionChange(select, this.selectStoreArr, this.agencyInfo.store_object, 'id', 2)
    },
        
     // store 单击行选中
    storeRowClick(row) {
      this.$select.rowClick(row, this.selectStoreArr, this.agencyInfo.store_object, this.$refs.storeTable, 'id')
    },
    
    // store 全选
    storeSelectAll(selection) {
      this.$select.selectAll(selection, this.storeList, this.agencyInfo.store_object, 'id', 2)
    },
        
      // 店铺商默认选中
    storeChecked() {
      this.$nextTick(() => {
        this.storeList.forEach((item, index) => {
          // 重置勾选项
          this.agencyInfo.store_object.forEach((m) => {
            if (item.id == m.id) {
              this.$refs.storeTable.toggleRowSelection(item, true)
            }
          })
        })
      })
    },
        
      // 关闭店铺对话框
    storeClose() {
      this.$refs.storeTable.clearSelection() // 取消勾选项
    },
    // 关闭tag标签
    closeStoreTag(item) {
     this.agencyInfo.store_object.splice(this.agencyInfo.store_object.indexOf(item), 1)
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 展开行 只展开一行

https://blog.csdn.net/qq_39923762/article/details/82886117 (opens new window) https://www.cnblogs.com/yearshar/p/11607252.html (opens new window)

   :row-key="getRowKeys"  //获取当前行id
   :expand-row-keys="expands"   //只展开一行放入当前行ranNum
   @row-click="rowClick"  //点击当前行
   :row-class-name="isShowIcon"//是否显示展开按钮
   @expand-change="exChange"  //展开收缩事件
1
2
3
4
5
 getRowKeys(row) {
        return row.ranNum;
      },

   // 点击行展开
    rowClick(row, e, column) {
      const NoIndex = column.type.indexOf('expand');
      if (NoIndex == 0 && row.style().length <= 0) {
        this.expands = [];
        return;
      }
      if (row.style.length > 0) {
        Array.prototype.remove = function (val) {
          const index = this.indexOf(val);
          if (index > -1) {
            this.splice(index, 1);
          }
        };
        if (this.expands.indexOf(row.ranNum) < 0) { // 确保只展开一行
          this.expands.shift();
          this.expands.push(row.ranNum);
        } else {
          this.expands.remove(row.ranNum);
        }
      } else {

      }
    },
    
    // 是否可以展开
    isShowIcon(row, index) {
      if (row.row.style.length > 0) return '';
      return 'hiderow';
    },
        
     // 展开收缩事件
    exChange(row, expanded) {
      if (expanded.length) {
        this.expands = [];
        if (row) {
          this.expands.push(row.ranNum);
        }
      } else {
        this.expands = [];
      }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# 前端分页

VUE结合elementUI(Pagination)进行前端分页 (opens new window)

<el-table
:data="tableData |pagination(pageNo,pageSize)">
<el-table>
1
2
3
filters: {
    pagination (array, pageNo, pageSize) {
      let offset = (pageNo - 1) * pageSize
      let data = (offset + pageSize >= array.length) ? array.slice(offset, array.length) : array.slice(offset, offset + pageSize)
      return data
    }
  }
1
2
3
4
5
6
7
lastUpdate: 5/13/2021, 5:35:14 PM