效果:
功能描述:
添加行:点击按钮,table表格新增一条数据。
导 入: 点击导入按钮,弹出上传文件组件,这里可以导入execl格式的表格,然后把导入的数据回显到table表格中。
操作栏: 点击删除按钮, 删除table表格此行数据。
table-header 搜索框: 输入内容,搜索出相对应的数据,主要用到了数组的filter方法。
分页: 点击分页,切换上一页,下一页,显示对应的数据。
代码:
<template>
<div>
// 按钮
<div class="btns-container">
<el-buttom size="small" type="primary" @click="addRow">添加</el-button>
<el-button size="small" type="primary" @click="import">导入</el-button>
</div>
// table 表格
<div class="table-container">
<el-table
:data="tableData"
border
highlight-current-row
>
<el-table-column label="index" type="index"/>
<template v-for="item in tableHeaders">
<el-table-column
:key="item.prop"
show-overflow-tooltip
:prop="item.prop"
:type="item.type"
>
// 这里是table-header栏
<template #header="scope"> // 这里是vue3的写法,如果是用的vue2,则可以改为: slot-scope="scope"即可
<span>{{item.label}}</span>
<template v-if="item.queryType==='input'">
<el-input
v-model="form[item.prop]"
:placeholder=`输入${item.label}`
/>
</template>
</template>
// 这里是 table - 行数据
<template v-if="item.queryType==='input'" #default="scope">
<el-input v-model="scope.row[item.prop]" placeholder="请输入"/>
</template>
</el-table-column>
</template>
// table - 操作栏
<el-table-column
label="操作"
>
<template #default="scope">
<el-button type="text" @click="deleteRow(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
// 分页
<div class="pagination-container">
<el-pagination
:current-page="pagination.currentPage"
:page-sizes="pagination.pageSizes"
:page-size="pagination.pageSize"
:layout="pagination.layout"
:total="pagination.total"
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
// 导入文件组件
<el-dialog
title="上传文件"
:visibile.sync="dialogVisible" // 这里的dialog组件可以进行再次封装
>
<upload-file
:type="xxx"
@submit="uploadSubmit"
@cancel="uploadCancel"
@getImportData="getImportData"
/>
</el-dialog>
</div>
</template>
<script>
// 引入导入文件组件
import uploadFile from 'xxxx -> 文件路径';
export default{
name:'xx',
components:{
uploadFile
},
data(){
return {
dialogVisible: false,
tableHeaders:[
{
label:'table栏一',
prop:'var1',
queryType:'input'
},{
label:'table栏二',
prop:'var2',
queryType:'input'
}
],
form:{
var1:'',
var2:'',
},
pagination:{
total:0,//总页数
currentPage:1,
pageSize:10,
layout:'sizes,prev,pager,next,jumper',
pageSizes:[10,20,30,40,50,100]
},
originTableData:[]
}
},
computed:{
tableData(){
const { pageSize, currentPage } = this.pagination;
// 当前页
const pre = (currentPage -1) * pageSize;
// 下一页
const next = pageSize * currentPage;
const formKeys = Object.keys(this.form);
const tableList = this.originTableData.slice(pre,next);
const tableFinally = tableList.filter((item) => {
let flag = true;
formKeys.forEach((key) => {
const formValue = this.form[key];
const itemValue = item[key];
flag = flag && ((!itemValue && !formValue) || (itemValue && itemValue.includes(this.form[key])));
})
return flag;
})
return tableFinally;
}
},
watch:{
originTableData:{
deep:true,
handler(){
this.pagination.total = this.originTableData.length;
}
}
},
methods:{
// 设置table数据
setOiginTableData(data){
this.originTableData = data;
},
// 获取table数据
getTableData(){
return this.originTableData;
},
// 添加行
addRow(){
this.originTableData.push({
var1:'',
var2:'',
})
},
// 导入
import(){
this.dialogVisible = true;
},
// 获取到导入文件的数据并追加到originTableData
getImportData(data){
this.dialogVisible = false;
this.originTableData = [...this.originTableData,...data];
},
uploadSubmit(){
this.dialogVisible = false;
},
uploadCancel(){
this.dialogVisible = false;
},
// 删除行数据
deleteRow(index){
const {pageSize, currentPage} = this.pagination;
const num = pageSize * (currentPage -1) + index;
this.originTableData.splice(num,1);
},
// 分页功能 - 页数据
handleCurrentChange(val){
this.pagination.currentPage = val;
},
// 分页功能 - pagesize 数据
handleSizeChange(val){
this.pagination.pageSize = val;
},
}
}
</script>
<style lang="scss" scoped>
// 改变element ui 组件自带得样式可以用
:deep .el-input {
}
</style>
补充:这里可以看一下导入文件的组件,因为采用的是vue3的写法, 上才艺,哦不,上代码~~~
<template>
<div>
<el-upload
class="upload-file"
action="#"
:headers="headers"
:multiple="false"
accept=".xls,.xlsx"
:on-change="uploadChange"
:on-success="uploadSuccess"
:http-request="httpRequest"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
将文件拖到此处,或 <em>点击上传</em>
</div>
</el-upload>
<span @click="handleDownloadTemplate">下载模板</span>
<div class="btns">
<el-button type="primary" @click="handleSubmit">确定</el-button>
<el-button @click="handleCancel">取消</el-button>
</div>
</div>
</template>
<script>
// 这里可以引入 相关api
export default{
name:'xxx',
props:{
type:{
type:String,
default:''
}
},
emits:['getImportData','submit','cancel'],
setup(props, {emit}){
//定义变量
const headers = { Authorization: token // 这里放token值哈 }
// 点击确定按钮触发的事件
const handleSubmit = async()=>{
emit('submit')
}
// 点击取消按钮触发的事件
const handleCancel = async()=>{
emit('cancel')
}
// 上传文件触发的事件
const uploadChange = (file)=>{
const {status} = file;
if(status ==='success'){
// 导入成功
}else if(status === 'error'){
// 导入失败
}
}
// 这个是上传成功后事件
const uploadSuccess = ()=>{}
// 自定义上传文件方法
const httpRequest = async (file)=>{
const data = new FormData();
data.append('file',file.file);
// 这里提一下,如果想获取props传递过来的数据,不能用 this.xxx,需要用 props.xxx,例如,
if(props.type==='xxx'){
// 直接请求相关api
}else{
// 请求api,假设该请求该api后还有返回值
const res = await xxxapi(data);
emit('getImportData',res); // 这里是把返回的数据通过emit上传到父组件
}
}
// 下载模板触发的事件
const handleDownloadTemplate = async ()=>{
const params = {};//参数
const res = await xxapi(params);
const {downloadUrl} = res; // 获取返回的下载地址
const DownloadLink = document.createElement('a');
DownloadLink.href= downloadUrl;
DownloadLink.style = 'display:none';//隐藏创建的a标签
document.body.appendChild(Downloadlink);
DownloadLink.click(); // 触发a标签的click事件
document.body.removeChild(DownloadLink)
}
return {
handleSubmit,
handleCancel,
headers,
uploadChange,
uploadSuccess,
httpRequest,
handleDownloadTemplate
}
}
}
</script>
至此,分享完毕,vue3感觉真不戳~~