一、组件封装需要注意什么?
组件化思想:组件应该是独立的、可复用的部件,应该遵循单一职责原则,将组件的功能划分得尽可能细致。
API 设计:组件的 API 设计要合理,要考虑到组件的可定制性和易用性。应该尽可能的提供必要的配置项和事件回调,同时避免提供过多的 API,导致 API 过于复杂。
生命周期:组件的生命周期要合理地使用,尤其是对于需要与外部交互的组件,要注意生命周期的时机,以便在组件的不同阶段进行相应的操作。
组件通信:组件通信是组件化开发中的一个重要问题,Vue 中提供了多种通信方式,包括props、 e m i t 、 emit、 emit、parent、$attrs、ref、vuex、provide/inject 等。在组件的设计中,需要考虑到组件之间的通信问题,合理地使用这些通信方式。
样式和布局:组件的样式和布局应该尽可能地与组件的功能分离,避免样式和布局影响到组件的功能和逻辑。
测试:组件封装完成后,需要进行充分的测试,包括单元测试和集成测试,以保证组件的质量和稳定性。
总的来说,组件封装可以达到代码的灵活和可复用性,但封装时要谨记上面提到的封装要点。
二、目标效果
组件可配置属性:
- multiple是否为多文件上传;
- filePostfix允许上传文件类型提示;
- fileList底部文件列表;
- loading加载数据时显示动效;
组件可配置方法:
- upload文件上传触发的事件回调;
- delete点击删除图标触发的事件回调;
- download点击下载图标触发的事件回调;
三、封装步骤
1、从本地选取文件
1)方式一——点击按钮选取文件:
<input ref="inputfile" class="file-content" type="file" :multiple="multiple" @change="handelInputFile">
相关方法:
handelInputFile(e) {
this.readFile(e.target.files)
this.$refs.inputfile.value = null;
},
2)方式二——直接拖拽文件:
<div class="file-box"
:class="dropType ? 'dropbox-shadow' : ''"
type="file"
v-i-loading.fullscreen="loading"
@dragenter.stop.prevent="fileBoxDragenter(true)"
@dragleave.stop.prevent="fileBoxDragleave"
@drop.stop.prevent="fileBoxDrop($event, true)"
@dragover.stop.prevent=""
@click="openFile">
<div>
<div class="upload-icon"></div>
</div>
<div class="upload-text">
<span>将文件拖到此处,或</span>
<span>点击上传</span>
<div class="el-upload__tip" slot="tip">只能上传{
{filePostfix}}文件,且不超过100M</div>
</div>
</div>
相关方法:
/**
* dragenter源对象进入过程对象范围内
*/
fileBoxDragenter(flag) {
// 传入10ms的延迟锁,让drapleave在enter延迟后触发
this.boxLock = true
setTimeout(() => {
this.boxLock = false
}, 10)
// dropType文件拖拽进选中范围的高亮效果
this.dropType = flag
},
/**
* dragleave源对象离开过程对象范围
*/
fileBoxDragleave() {
if (this.boxLock) return
this.dropType = false
},
/**
* drop文件拖拽落下
*/
fileBoxDrop(e) {
this.dropType = false
let fileList = e.dataTransfer.files
this.readFile(fileList)
},
2、获取上传的文件
readFile(fileList) {
if (!fileList || fileList.length < 1) return
if(fileList.length > 1) {
this.$Imessage({
message: `不支持一次上传多文件`,
type: 'warning'
})
return
}
if(!this.multiple && this.fileList.length >= 1) { // 仅允许单个附件上传
this.$Imessage({
message: `不支持上传多个附件`,
type: 'warning'
})
return
}
let file = fileList[0]
if(this.validFile(file)) {
tempFile = file
this.$refs['paramForm'].validate(valid => {
if(valid) {
this.$emit('upload', tempFile, this.multiple)
}
})
}
},
3、已上传文件展示、删除、下载
<!--已上传文件展示-->
<ul v-show="fileList.length>0" class="file-list">
<li v-for="(item, index) in fileList" class="item-content">
<a :title="item.name">