当前位置: 首页 > news >正文

Vue+element ui导入组件封装——超级优雅版

在这里插入图片描述

Vue.js 关于表格合并篇

    • 1. 需求说明
    • 2. 第一个版本
    • 3. 让人脑壳疼的地方
    • 4. 程序思维至关重要
    • 5. 有必要提一下面向对象编程

1. 需求说明

  • 目前是开发管理系统,那肯定免不了有各种导入文件
  • 所以封装一个全项目通用的是十分有必要的
  • 本文由浅入深,通俗易懂

2. 第一个版本

  • 封装组件这玩意对于大家来说其实不是什么难事
  • 所以第一个版本一下就写出来了,是这个样子的
    在这里插入图片描述
  • 不同的场景会有一个唯一的sign值,在下载模板以及导入的时候传给后端
  • 并且提供了其它参数供选择:otherParams,有时候传文件也需要附带参数
  • 代码如下(注释也尽可能详尽了)
<template><div><el-dialog:title="dialogTitle":visible.sync="visible"width="620px":close-on-click-modal="false"@opened="Opened()"@closed="Closed('ruleForm')"><div><!-- 导入说明 --><div class="import-explain"><h3 class="import_item_title">·&nbsp;&nbsp;导入说明</h3><div class="tipContent"><spanv-for="(item, index) in htmlList":key="index"@click="textTap"v-html="index + 1 + '.' + item"></span></div></div><div class="import-file"><h3 class="import_item_title">·&nbsp;&nbsp;<slot name="importTitle">导入文件</slot></h3></div><div class="select-file"><el-uploadref="upload"accept=".xls,.xlsx":action="uploadUrl":data="{ ...queryData, ...params, ...otherParams }":on-preview="handlePreview":on-remove="handleRemove":before-remove="beforeRemove":on-exceed="handleExceed":on-change="handleChang":on-success="handleSuccess":headers="headers":auto-upload="false":file-list="fileList"multiple:limit="limit > 1 ? limit : undefined"><el-button size="small" type="primary">选择文件</el-button><span>&nbsp;&nbsp;文件格式支持xls,xlsx</span></el-upload></div></div><span slot="footer" class="dialog-footer"><el-button @click="visible = false">取 消</el-button><el-button type="primary" @click="handleConfirm('ruleForm')">确 定 导 入</el-button></span></el-dialog></div>
</template><script>
import { download } from "@/api/data.js";
import { downloadFileUrl } from "@/utils/index.js";
import { getToken } from "@/utils/auth";
export default {name: "importFile",props: {dialogTitle: {//弹窗标题type: String,default: "导入文件",},uploadUrl: {//导入地址type: String,default: "",},limit: {//上传最大文件数type: Number,default: 1,},headers: {//文件上传自定义请求头信息type: Object,default: function () {return {Authorization: getToken(),};},},htmlList: {//提示信息列表type: Array,default: Array,},queryData: {//导入接口所需的数据type: Object,default: Object,},otherParams: {type: Object,},},data() {return {visible: false,params: {otherParams: undefined, //{}其他参数}, //导入参数fileList: [],selectFile: false, //false 未上传文件  true 已上传文件};},created() {console.log("create", this.headers);},mounted() {},methods: {//弹框打开Opened() {},//弹框关闭Closed() {this.fileList = []; //上传的导入文件置空this.selectFile = false;},//确定导入handleConfirm() {if (this.selectFile) {this.$refs.upload.submit();} else {this.$message.error("请选择需要上传的文件!");}},//点击文件列表中已上传的文件时的钩子handlePreview(file) {this.$emit("handlePreview", {file: file,});},//文件列表移除文件时的钩子handleRemove(file, fileList) {this.selectFile = false;this.$emit("handleRemove", {file: file,fileList: fileList,});},//删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。beforeRemove(file, fileList) {this.$emit("beforeRemove", {file: file,fileList: fileList,});},//文件超出个数限制时的钩子handleExceed(files, fileList) {this.$emit("handleExceed", {file: files[0],fileList: fileList,});},//文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用handleChang(file, fileList) {// 仅上传一个文件 多次选择文件时 覆盖之前的文件if (this.limit == 1) {if (fileList.length > 0) {this.fileList = [fileList[fileList.length - 1]]; //这一步,是 展示最后一次选择文件}}this.selectFile = true;},//文件上传成功时的钩子handleSuccess(response, file, fileList) {if (response.code != 200) {this.$message.error(response.message);} else {this.$refs.upload.clearFiles();this.$emit("handleSuccess", {response: response,file: file,fileList: fileList,});}},textTap(e) {if (e.target.dataset.type == "download") {e.preventDefault();const url = e.target.dataset.url;const sign = e.target.dataset.sign;const title = e.target.innerText;let params = {};if (sign) {params.sign = sign;}download(url, params).then((res) => {downloadFileUrl(res, "application/vnd.ms-excel", title, "xlsx");});}},},
};
</script><style lang="scss" scoped>
.import-file {margin-top: 15px;margin-bottom: 15px;
}.select-file,
.tipContent {margin-left: 16px;
}//导入说明
.import-explain {// margin-top: 15px;
}:deep(.import_item) {margin-top: 15px;
}:deep(.import_item_title) {display: block;margin: 0;width: 100%;font-size: 18px;color: #333;line-height: 2;
}:deep(.import_item_content) {margin-left: 16px;margin-top: 15px;
}.tipContent {display: flex;justify-content: flex-start;align-items: flex-start;flex-direction: column;margin-top: 15px;
}.tipContent span {line-height: 1.8;
}.tipContent a {color: #46a6ff;
}
</style>
  • 这个是低耦合的,并且非常通用,大家可以直接CV,该有的各种函数以及检测都到位了,样式也提供在这里
  • 调用的时候,也很简单
<DialogUploadFile :dialogTitle="'导入'" :dialogVisible="dialogVisibleImport" :htmlList="importHtmlList" :uploadUrl="uploadUrl" :queryData="{ sign: signTest }" @handleSuccess="uploadSuccess"@close="dialogBeforeClose">
</DialogUploadFile>
  • importHtmlList,这个就是那个文本了,导入说明。

3. 让人脑壳疼的地方

  • 这个组件封装一两年了,也没发现有啥问题,能够正常使用,直到最近…
  • 在产品需求这块,发现会有一些情况,加了一些输入框,需要收集其他信息,如下:
    在这里插入图片描述
  • 还有些逻辑:比如切换以及验证
    在这里插入图片描述

4. 程序思维至关重要

  • 那么,各位朋友们,这种问题要怎么解决呢?由基础版升级到这种复杂的
  • 难点在于:不能影响之前的逻辑及业务,又要进行功能升级
  • 首先想到的应该是加各种 if 了,也就是直接在公用组件里面修改,外部传值进来,如下:
    在这里插入图片描述
  • 这样确实能解决问题,但是吧,以后每次新增功能,都要新增各种 if ,但是十分不建议的:
  • 这是公用组件,整个项目都在用,万一哪天被某个人改错了,风险是非常大的,等着挨骂吧
  • 甚至于,以后代码量干到几百行,谁还看得懂,请神吧(工具组件应该尽量简洁)

5. 有必要提一下面向对象编程

  • 这玩意确实比较抽象,很多人做了好几年程序员也搞不懂
  • 首先,肯定不是把你对象请到公司,坐你对面,然后你看着她写代码
  • 简而言之:各个组件 / 方法,都应该保持独立,有自己的私有的方法与属性,提供接口给外部调用。你只能通过调用我的方法改变我的属性,不能乱来,就跟打狗还得看主人一样。
  • 放在上传组件上来说,这些业务判断是不能放到公用组件的,甚至于说“玷污了”它,只能写到调用它的组件里面去:公用方法或组件尽量不涉及具体业务逻辑
  • 所以,其实一个插槽就能搞定
    在这里插入图片描述
  • 这些新的参数(下拉框及时间区间),以及验证必填的逻辑,通通放到父组件去,如下:
<DialogUploadFile :dialogTitle="'导入'" :dialogVisible="dialogVisibleImport" :checkChildData="checkChildData":htmlList="importHtmlList" :uploadUrl="uploadUrl" :queryData="{ sign: signTest }" @handleSuccess="uploadSuccess"@close="dialogBeforeClose"><template v-slot:otherDataSlot><!-- 通通放在这里 --></template>
</DialogUploadFile>
  • 验证方法:checkChildData,加一个参数即可,也在调用上传组件的地方定义好
  • 在确认导入之前,调用该方法,符合条件返回 true,反之返回false即可

1. 希望本文能对大家有所帮助,如有错误,敬请指出
2. 原创不易,还请各位客官动动发财的小手支持一波(关注、评论、点赞、收藏)
3. 拜谢各位!后续将继续奉献优质好文
4. 如果存在疑问,可以私信我(文底有V)

在这里插入图片描述

http://www.dtcms.com/a/499690.html

相关文章:

  • Orleans StreamInstruments 作用分析
  • 全虚拟化、半虚拟化和SR-IOV直通-三种I/O虚拟化技术的核心差异
  • 《打造国漫唐风沉浸感:角色衣袂物理模拟的场景化技术方案》
  • 【三维分割】LangSplatV2:高维的语言3DGS,快到450+FPS
  • Kubernetes(k8s) —— 简介
  • 雅安工程交易建设网站建高级网站
  • 不止于S3:RustFS的多协议网关之路,如何平滑对接HDFS与WebDAV?
  • GIT 实战命令操作大全,代码变动,推动,修改备注,撤销(篇幅一)
  • 网站建设的 关键词家具公司网页设计
  • 蓝牙HCI指令
  • git命令——基础
  • 网站建设的总结200字wordpress长微博工具
  • Qt Q_ENUM和Q_ENUM_NS的区别?
  • 【机器人学中的状态估计】2.1 习题:证明p维高斯概率密度函数积分为1
  • 网站建设合同范本简易版邯郸有什么互联网大公司吗
  • 凡科建站的怎么取消手机网站怎么登录住建局官网
  • 什么是智能管理平台?
  • 《录井工程与管理》——第七章 录井资料处理技术
  • 温州瓯北做网站最好看的免费观看全集电视剧
  • 做网站上传图片做网站做app什么专业
  • 【OpenHarmony】外部设备管理器架构
  • 从头开始为 ARM 创建 Ubuntu 映像
  • Android 开发 | 如何使用命令使 Android 应用进入调试状态
  • 在线下单网站怎么做国家企业信用信息查询公示系统广东
  • 企业营销网站建设策划书邯郸市人社局
  • 中山哪里可以做网站产品推广方案ppt
  • 城管综合执法办案系统的技术体系解析:从移动端到云端
  • 开发基于AKS能运维开工单的智能体应用
  • 3D生成软件Rodin 2.0 简单测试案例
  • vivado 从已实现的设计工程创建自定义PL IBIS文件方法