# 表格的添加删除
<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
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
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
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表格
<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
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
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
2
3
# 导出excel表格
- 后台返回的是数据
- 方法一 推荐
文档 (opens new window)
安装插件
npm install xlsx file-saver -S
npm install script-loader -S -D
1
2
3
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
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
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
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
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
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
2
3
4
5
:row-key="getTaskRowKeys" //table属性
// 返回id设置row-key
getTaskRowKeys (row) {
return row.id
}
1
2
3
4
5
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
2
3
4
5
6
7
8
data(){
return{
getRoleRowKeys (row) {
return row.id
}
}
1
2
3
4
5
6
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
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
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
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
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
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
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
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
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
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
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
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
2
3
4
5
6
7