培训人员网站建设,网站如何做排名,南宁排名推广,wordpress 动态主题文章目录 前言组件功能概述实现效果组件模板结构组件的核心逻辑1.数据属性定义2.方法拆解3.CSV 文件解析方法4. 错误处理方法 组件样式完整组件代码总结待优化的地方 前言
在 Vue2 项目中#xff0c;我们经常需要封装一些可重用的组件来提升开发效率。本文将介绍如何使用 Vue… 文章目录 前言组件功能概述实现效果组件模板结构组件的核心逻辑1.数据属性定义2.方法拆解3.CSV 文件解析方法4. 错误处理方法 组件样式完整组件代码总结待优化的地方 前言
在 Vue2 项目中我们经常需要封装一些可重用的组件来提升开发效率。本文将介绍如何使用 Vue2 和 Element UI 封装一个用于上传 CSV 文件并在对话框中回显其内容的公共组件。此组件共涉及两个接口一个用于校验 CSV 文件内容是否合规另一个用于上传经过校验的 CSV 文件。
组件功能概述
该组件主要包括以下功能
选择 CSV 文件并上传。校验文件内容是否符合要求。将文件内容以表格形式展示。支持对不合规内容进行标记和提示。用户可在确认内容无误后手动点击上传。
实现效果 组件模板结构
首先来看组件的模板部分。
templateel-dialog:visible.syncvisibletitle上传 CSV 文件width50%:before-closehandleClose:close-on-click-modalfalseel-upload:action!validateStatus ? validate : action:before-uploadbeforeUpload:show-file-listfalse:headersheadersrefupload:on-successhandleAvatarSuccess:auto-upload!validateStatus:file-listfileList:on-errorerrorFnel-button typeprimary clickselectFile选择 CSV 文件/el-button/el-uploadel-tablev-iftableData.length 0:datatableData.slice(1)stylewidth: 100%; margin-top: 20pxborderel-table-columnv-for(header, index) in tableData[0]:keyheader- index:propcol- index:labelheadertemplate slot-scopescopediv :class{ error-cell: scope.row[index].value.isError }{{ scope.row[index].value.value }}el-tooltipclassitemeffectdarkplacementtopv-ifscope.row[index].value.isErrortemplate slotcontent{{ scope.row[index].value.errorMsg }}/templatei classel-icon-question/i/el-tooltip/div/template/el-table-column/el-tablespan slotfooter classdialog-footerel-button clickhandleClose关 闭/el-buttonel-buttontypeprimaryclickhandleConfirm:disabled!validateStatus:title!validateStatus ? 请上传文件并通过校验 : 点击上传文件确定上传/el-button/span/el-dialog
/template在这个模板中使用了 Element UI 的 el-dialog 作为弹出框el-upload 作为上传组件el-table 显示上传的 CSV 文件内容。组件的主要逻辑操作通过各种方法methods来实现。
组件的核心逻辑
1.数据属性定义
以下是组件的数据属性用于存储上传文件的状态、表格数据和 HTTP 请求头信息
data() {return {tableData: [], // 存储解析后的表格数据headers: {Authorization: Bearer getToken(),},validateStatus: false,fileList: [], // 存储上传的文件};
}tableData存储解析后的 CSV 文件数据。headersHTTP 请求头包含授权信息。validateStatus文件校验状态决定文件是否可以被上传。fileList用于存储选择的 CSV 文件。
2.方法拆解
selectFile() 方法
selectFile() {this.validateStatus false;
}当用户点击“选择 CSV 文件”按钮时重置 validateStatus 状态为 false确保在选择新文件时校验状态被重置
validateData(data) 方法
validateData(data) {const allData Object.values(data).flat();// 检查是否所有的 isError 都为 falseconst allValid allData.every((item) !item.isError);if (allValid) {this.validateStatus true;this.$message.success(校验通过可以上传);} else {this.validateStatus false;this.$message.error(请按要求重新修改上传内容);}
}该方法用于校验上传的数据如果数据无误则设置 validateStatus 为 true并显示成功提示否则显示错误提示。
handleAvatarSuccess(res, file) 方法
handleAvatarSuccess(res, file) {if (res.code 500) {this.$message.error(res.msg);this.validateStatus false;return;}if (res.data) {const csvHeaders this.tableData[0];const fields Object.keys(res.data);const dataLength res.data[fields[0]].length;const result Array.from({ length: dataLength }, (_, index) fields.map((field) ({value: res.data[field][index],isError: false,errorMsg: ,})));this.tableData [csvHeaders, ...result];this.validateData(res.data);}
}该方法在文件上传成功后调用处理上传成功后的逻辑包括数据解析和更新表格数据。
handleClose() 方法
handleClose() {this.tableData [];this.$emit(update:visible, false);
}关闭对话框时清空表格数据并触发 visible 属性更新事件关闭对话框。
handleConfirm() 方法
handleConfirm() {const formData new FormData();formData.append(file, this.fileList[0]);const config {headers: this.headers,};axios.post(this.action, formData, config).then((response) {if (response.data.code 500 response.data.msg null) {this.$message.error(文件提交失败,未知原因);} else if (response.data.code 200) {this.$message({dangerouslyUseHTMLString: true,message: response.data.msg,type: success,duration: 5000,});this.$emit(upload-success);}}).catch((error) {this.$message.error(文件提交失败);});
}该方法在用户确认上传时调用通过 Axios 发起 POST 请求将文件上传至后端接口。
3.CSV 文件解析方法
beforeUpload(file) 方法
beforeUpload(file) {if (!this.validateStatus) {const reader new FileReader();reader.onload (e) {const decoder new TextDecoder(gbk);const csvText decoder.decode(e.target.result);this.tableData this.parseCSV(csvText);if (this.tableData.length 0) {return true;} else {return false;}};reader.readAsArrayBuffer(file);this.fileList [file];} else {return true;}
}该方法在文件上传之前执行使用 FileReader 对象解析 CSV 文件内容并将其转换为表格数据。
parseCSV(text) 方法
parseCSV(text) {const lines text.split(\n).map((line) line.trim());if (lines.length 0) return [];const headers this.parseLine(lines[0]);const data lines.slice(1).map((line) {const cells this.parseLine(line);const row headers.map((header, index) ({value: cells[index] || ,isError: false,errorMsg: ,}));return row;});return [headers, ...data];
}该方法用于解析 CSV 文件内容按行拆分并解析每一行内容为表格所需的格式。
4. 错误处理方法
errorFn(err, file, fileList) 方法
errorFn(err, file, fileList) {console.log( ~ errorFn ~ err:, err);
}该方法处理文件上传过程中的错误当前仅简单地打印错误信息。
组件样式
style scoped
.el-table th,
.el-table td {text-align: center;padding: 10px;
}.error-cell {background-color: #ffb1b1;color: black;padding: 5px;
}
/style此部分为组件的样式定义确保表格居中对齐并为有错误的单元格添加红色背景。
完整组件代码
完整的组件代码如下所示。这段代码结合了 Vue2 和 Element UI封装了一个 CSV 文件上传与显示的功能组件。
templateel-dialog:visible.syncvisibletitle上传 CSV 文件width50%:before-closehandleClose:close-on-click-modalfalseel-upload:action!validateStatus ? validate : action:before-uploadbeforeUpload:show-file-listfalse:headersheadersrefupload:on-successhandleAvatarSuccess:auto-upload!validateStatus:file-listfileList:on-errorerrorFnel-button typeprimary clickselectFile选择 CSV 文件/el-button/el-uploadel-tablev-iftableData.length 0:datatableData.slice(1)stylewidth: 100%; margin-top: 20pxborderel-table-columnv-for(header, index) in tableData[0]:keyheader- index:propcol- index:labelheadertemplate slot-scopescopediv :class{ error-cell: scope.row[index].value.isError }{{ scope.row[index].value.value }}el-tooltipclassitemeffectdarkplacementtopv-ifscope.row[index].value.isErrortemplate slotcontent{{ scope.row[index].value.errorMsg }}/templatei classel-icon-question/i/el-tooltip/div/template/el-table-column/el-tablespan slotfooter classdialog-footerel-button clickhandleClose关 闭/el-buttonel-buttontypeprimaryclickhandleConfirm:disabled!validateStatus:title!validateStatus ? 请上传文件并通过校验 : 点击上传文件确定上传/el-button/span/el-dialog
/templatescript
import { getToken } from /utils/auth;
import axios from axios;
export default {props: {visible: {type: Boolean,required: true,},action: {type: String,required: true,},validate: {type: String,required: true,},},data() {return {tableData: [], // 存储解析后的表格数据headers: {Authorization: Bearer getToken(),},validateStatus: false,fileList: [], // 存储上传的文件};},methods: {selectFile() {this.validateStatus false;},validateData(data) {const allData Object.values(data).flat();const allValid allData.every((item) !item.isError);if (allValid) {this.validateStatus true;this.$message.success(校验通过可以上传);} else {this.validateStatus false;this.$message.error(请按要求重新修改上传内容);}},handleAvatarSuccess(res, file) {if (res.code 500) {this.$message.error(res.msg);this.validateStatus false;return;}if (res.data) {const csvHeaders this.tableData[0];const fields Object.keys(res.data);const dataLength res.data[fields[0]].length;const result Array.from({ length: dataLength }, (_, index) fields.map((field) ({value: res.data[field][index],isError: false,errorMsg: ,})));this.tableData [csvHeaders, ...result];this.validateData(res.data);}},handleClose() {this.tableData [];this.$emit(update:visible, false);},handleConfirm() {const formData new FormData();formData.append(file, this.fileList[0]);const config {headers: this.headers,};axios.post(this.action, formData, config).then((response) {if (response.data.code 500 response.data.msg null) {this.$message.error(文件提交失败,未知原因);} else if (response.data.code 200) {this.$message({dangerouslyUseHTMLString: true,message: response.data.msg,type: success,duration: 5000,});this.$emit(upload-success);}}).catch((error) {this.$message.error(文件提交失败);});},beforeUpload(file) {if (!this.validateStatus) {const reader new FileReader();reader.onload (e) {const decoder new TextDecoder(gbk);const csvText decoder.decode(e.target.result);this.tableData this.parseCSV(csvText);if (this.tableData.length 0) {return true;} else {return false;}};reader.readAsArrayBuffer(file);this.fileList [file];} else {return true;}},errorFn(err, file, fileList) {console.log( ~ errorFn ~ err:, err);},parseCSV(text) {const lines text.split(\n).map((line) line.trim());if (lines.length 0) return [];const headers this.parseLine(lines[0]);const data lines.slice(1).map((line) {const cells this.parseLine(line);const row headers.map((header, index) ({value: cells[index] || ,isError: false,errorMsg: ,}));return row;});return [headers, ...data];},parseLine(line) {const result [];let current ;let inQuotes false;for (let i 0; i line.length; i) {const char line[i];if (char ) {inQuotes !inQuotes;} else if (char , !inQuotes) {result.push(current.trim());current ;} else {current char;}}result.push(current.trim());return result;},},
};
/scriptstyle scoped
.el-table th,
.el-table td {text-align: center;padding: 10px;
}.error-cell {background-color: #ffb1b1;color: black;padding: 5px;
}
/style总结
通过本文的介绍了解了如何使用 Vue2 和 Element UI 封装一个 CSV 文件上传和回显的组件。该组件的设计充分考虑了数据校验和用户体验使得上传和展示过程更加直观和友好。在实际项目中可以根据业务需求对该组件进行扩展和定制。希望这篇文章对您有所帮助
待优化的地方
文件handleAvatarSuccess可以优化生成的数据有点冗余过于嵌套了。