項目中需要使用到文件上傳。我這里自己定義了一個上傳文件的組件
支持顯示上傳進度顯示(我這里顯示的是真實的上傳進度,當然,這個可以根據你自己的需求修改)。
支持多文件上傳。
最終效果如下:
代碼:
Uploads.vue
<template>
<div class="myUpload">
<!-- 上傳文件列表 -->
<div class="myUpload-img center" v-for="(item,index) in mydata" :key="index">
<img :src="item.url" v-if="type=='image'" />
<div class="fileLogo" v-else>
{{item.ext}}
</div>
<!-- 刪除文件 -->
<div class="delete" @click="del(item)">
<i class="icon-delete">+</i>
</div>
</div>
<!-- 上傳框 -->
<label class="btn center" v-if="(limit == 1 && mydata.length < 1) || limit > 1">
<i class="icon-add">+</i>
<!-- 多圖 -->
<input type="file" v-if="multiple == 1 " multiple class="inputfile" @change="handlerUpload($event)" :accept="accept" />
<!-- 單圖 -->
<input type="file" v-else class="inputfile" @change="handlerUpload($event)" :accept="accept" />
</label>
</div>
</template>
<style scoped>
@import "../../assets/css/components/pc/Uploads.scss";
</style>
<script>
// 引入js文件
import Uploads from "/@/assets/js/components/pc/Uploads";
// 使用js對象
export default {
...Uploads,
};
</script>
Uploads.ts
// 引入路由
import { useRouter, useRoute } from "vue-router";
import {
PropType,
ref,
watch,
reactive,
toRefs,
inject,
provide
} from "vue";
import { common, userinfo } from "/@/hooks/common.ts";
// 引入公共js文件
import utils from "/@/assets/js/public/function";
// 引入axios鈎子
import axios from "/@/hooks/axios.ts";
export default {
name: "Uploads",
/**
* @name: 父組件傳遞來的參數
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-01-10
*/
props: {
// 多文件上傳(0:單文件上傳,1:多文件上傳)
multiple:{
type: Number,
default: 0,
},
// 上傳數量
limit:{
type: Number,
default: 0,
},
// 上傳地址 url
action:{
type: String,
default: '',
},
// 文件類型
ext:{
type: Array,// 數組類型
default: [".gif", ".jpeg", ".jpg",".png",".bmp",".doc",".docx",".xls",".mp4",".rmvb",".zip"],
},
// 文件大小(mb)
size:{
type: Number,
default: 0,
},
// 列表初始值
data:{
type: Array,// 數組類型
default: [],
},
// 上傳文件類型(image | file)
type:{
type: String,
default: 'image',
},
// 隨機名(1或者0)
autoName:{
type: Boolean,
default: 1,
}
},
// VUE3語法 setup函數
// setup官方文檔:https://www.vue3js.cn/docs/zh/guide/composition-api-setup.html#參數
setup(props: any, content: any)
{
const router = useRouter();
/**
* @name: 聲明data
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-01-10
*/
const data = reactive({
mydata: props.data ? props.data.slice() : [],
accept: props.ext,
});
/**
* @name: 整理目前已有文件
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-02-20
* @param: file object 文件對象
* @param: obj object 文件上傳成功之后返回的信息對象
*/
const isImg = (file:any, obj:any) => {
if (props.type == "image")
{
let fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = function (ev:any) {
// 這是base64文件編碼
// obj.url = ev.target.result;
if(props.limit == 1)
{
data.mydata = [];
}
data.mydata.push(obj);
};
}
else
{
if (props.limit == 1)
{
data.mydata = [];
}
data.mydata.push(obj);
}
};
/**
* @name: 刪除文件
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-02-20
* @param: item object 文件信息
*/
const del = (item:any) => {
data.mydata = data.mydata.filter(function (obj:any) {
return obj != item;
});
};
/**
* @name: 組裝上傳數據(可多文件上傳)
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-02-20
* @param: e obj 文件流
*/
const handlerUpload = (e:any) => {
var file = '';
// 判斷文件上傳數量是否超限
if (data.mydata.length >= props.limit)
{
utils.alertMsg(2000, '上傳文件數量已達到上限!'); return;
}
for (var i = 0; i < e.target.files.length; i++)
{
// 判斷文件上傳數量是否超限
if (data.mydata.length >= props.limit)
{
utils.alertMsg(2000, '上傳文件數量已達到上限!'); return;
}
file = e.target.files[i];
// 上傳文件信息
let dataObj = {
file: file,
ext: data.accept,
size: props.size,
autoName: props.autoName == 0 ? props.autoName : 1
};
// 調用上傳方法
postUpload(dataObj)
.then(function (res: any) {
let obj = res.data;
isImg(file, obj);
utils.alertMsg(2000, '操作成功!'); return;
})
.catch(function (error: any) {
console.log(error);
utils.alertMsg(2000, error.data.msg); return;
});
}
};
/**
* @name: 上傳接口
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-02-18
* @param: data object 上傳文件數據對象
*/
const postUpload = (data:any) => {
var obj = new FormData();
for (let item in data)
{
obj.append(item, data[item]);
}
let config = {
headers: {
"Content-Type": "multipart/form-data"
},
onUploadProgress: (e:any) => {
var completeProgress = ((e.loaded / e.total) * 100) | 0;
// props.progress = completeProgress; //上傳過程
// 關閉 上傳進度顯示
utils.alertLoadExec(false);
utils.alertLoadExec(true, '上傳進度:'+completeProgress+'%');
}
};
return new Promise(function (resolve, reject) {
axios
.post(props.action, obj, config)
.then(function (res) {
// 關閉 上傳進度顯示
utils.alertLoadExec(false);
if (res.data.code == 1)
{
resolve(res);
}
else
{
reject(res);
}
})
.catch(function (error) {
reject(error);
// 關閉 上傳進度顯示
utils.alertLoadExec(false);
});
});
}
/**
* @name: 將data綁定值dataRef
* @author: camellia
* @email: guanchao_gc@qq.com
* @date: 2021-01-10
*/
const dataRef = toRefs(data);
return {
isImg, handlerUpload, postUpload, del,
...dataRef
}
}
};
Uploads.scss
i {
font-style: normal;
}
.myUpload {
display: flex;
}
.inputfile {
width: 0px;
height: 0px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.btn {
width: 200px;
height: 200px;
border-radius: 4px;
font-size: 3rem;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border: 1px dashed rgb(107 60 60);
color: rgb(72 41 41);
}
.btn:hover {
color: #6bc7ff;
border-color: #6bc7ff;
}
.myUpload-img {
width: 200px;
height: 200px;
margin-right: 10px;
position: relative;
border-radius: 4px;
border: 1px dashed#ccc;
}
.myUpload-img:hover .delete {
display: flex;
}
.myUpload-img:hover {
border-color: red;
}
.myUpload-img img {
width: 100%;
height: 100%;
}
.myUpload-img .fileLogo {
color: #adadad;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: absolute;
top: 0;
bottom: 0;
text-transform: uppercase;
font-size: 3rem;
}
.myUpload-img .delete {
width: 100%;
height: 100%;
border-radius: 4px;
position: absolute;
background: rgba(0, 0, 0, 0.4);
top: 0;
bottom: 0;
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
}
.icon-delete {
color: red;
font-size: 3rem;
transform: rotate(45deg);
}
.center{
margin:auto;
}
上傳進度彈窗代碼:
utils
.
alertMsg
調用實例:父組件傳入子組件的參數,我在子組件ts文件中都有注釋。
<Uploads class="upload" :limit="1" :type="'image'" :ext="ext" :data="userLogoInfo"
:action="'后端上傳地址'" :autoName="1" :size="5*1024*1024" :multiple="0">
</Uploads>
以上大概是我自定義上傳組件的全部代碼。
有好的建議,請在下方輸入你的評論。
歡迎訪問個人博客
https://guanchao.site
歡迎訪問小程序: