背景:使用的vant 组件开发钉钉H5微应用,但是钉钉对vant 的图片是不兼容的,因此这个上传图片的组件,在手机上默认图片加载不出来,是一个灰色的框。
功能:要实现上传,展示,回显的功能
给input 的type属性设置成file属性,通过label来绑定这个input ,来获取到这个图片的file 对象
通过 new FileReader() 这个对象中的方法,来本地的解析这个选择的file对象
FileReader.readAsDataURL() 方法, 开始读取指定的 Blob 中的内容。一旦完成,result 属性中将包含一个 data: URL 格式的 Base64 字符串以表示所读取文件的内容。可以获取到这个file对对象的本地base64 格式的内容,来实现图片的展示
通过发送请求,将这个file 对象发送到服务器,根据返回的地址进行处理,传到父组件使用
至于回显功能:由于使用了vant 组件 所以直接使用了一个遮罩层
上传组件
<template>
<div style="position: relative" class="box">
<div class="upload">
<label for="file" class="custom-file-upload" v-if="flag">
<div class="btn">点击上传图片</div>
</label>
<input
@change="onchange"
type="file"
name=""
id="file"
accept="image/*"
style="display: none"
/>
<div class="preview">
<van-image width="100" height="100" :src="src" @click="imgClick" />
<span
class="del"
@click="delHandler"
v-if="this.src != this.defaultImage && flag"
>✖</span
>
</div>
</div>
<van-overlay :show="show" @click="overlayHandler">
<div class="wrapper">
<van-image :src="src" />
</div>
</van-overlay>
</div>
</template>
<script>
import CryptoJS from "crypto-js";
import { Base64 } from "js-base64";
export default {
props: {
//回显的图片地址
fileUrl: {
type: String,
default: () => "",
},
},
data() {
return {
defaultImage:
"https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png",//进行对比的图片
src: "https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png",//进行渲染的图片
show: false,
file: null,
tool: "",
flag: true,
};
},
methods: {
onchange(e) {
this.file = e.target.files[0];
// 定一个一个formdata 对象
let formData = new FormData();
formData.append("file", this.file);
formData.append("insert", JSON.stringify({}));
// 向存储图片的服务器发送请求
R.Ding.uploadFile("?resignation", formData).then((res) => {
if (res.status == 200) {
// 替换返回字符串的格式
let aaa = res.data.replaceAll("\\", "/");
aaa = aaa.substring(3, aaa.length);
let url = `域名${aaa}`;
// 将服务器返回的地址传递回去
this.$emit("href", url);
}
});
// 读取出来这个文件
// 创建一个FileReader 对象
const reader = new FileReader();
// 可以将file 文件解析成一个base64
reader.readAsDataURL(this.file);
// 这里是异步的`
reader.onload = (e) => {
// 把数据读出来生成一个本地DataURL
// 读取出来的文件赋值给img 实现本地预览
this.src = e.target.result;
};
},
// 删除图片
delHandler() {
this.src = this.defaultImage;
this.file = null;
this.$emit("href", null);
},
//点击图片
imgClick() {
if (this.src == this.defaultImage) {
return;
} else {
this.show = true;
}
},
// 点击遮罩层
overlayHandler() {
this.show = false;
console.log(1111);
},
},
computed: {},
watch: {},
created() {},
mounted() {
//图片回显
this.$nextTick(() => {
if (this.fileUrl != "") {
this.src = this.fileUrl;
this.flag = false;
}
});
},
};
</script>
<style scoped>
.box {
}
.upload {
display: flex;
flex-direction: column;
}
.show {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #000;
/* opacity: .8; */
}
.show_img {
}
.preview {
position: relative;
width: 100px;
height: 100px;
overflow: hidden;
/* 添加这一行 */
}
.del {
cursor: pointer;
font-size: 12 px;
text-align: center;
line-height: 25px;
color: #fff;
position: absolute;
width: 25px;
height: 25px;
background-color: #000;
border-radius: 50%;
right: -5px;
top: -5px;
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.btn {
color: #fff;
background-color: #1989fa;
width: 110px;
height: 30px;
text-align: center;
line-height: 30px;
border-radius: 5px;
margin: 10px 0;
font-size: 15px;
}
</style>
父组件使用
在子组件上自定义一个事件,来获取传递过来的地址
<div class="fieldBox">
<div class="fieldTit"><span class="star">*</span>工号报删凭证:</div>
<div class="upload">
<Upload :fileUrl="fileUrl" @href="loadHandler"></Upload>
</div>
</div>
// js
// 封装upload返回的图片地址
loadHandler (url) {
this.dataObj.fileFrom = url;
console.log(url)
},