学习记录:
需求:定义一个图片上传/预览/放大效果公共组件。
<template>
<div class="image-picker">
<!-- 文字时 -->
<span v-if="viewImgTitle" @click="viewBigImg" class="view-image-title">{{viewImgTitle}}</span>
<!-- 图片展示形式 -->
<div
:class="['avatar-uploader', {'avatar-uploader_border' : avaterUploadImg}, {'cursor' : !isNeedUpload}]"
:style="{'width':width,'height':height}"
@click="viewBigImg('img')"
v-else
>
<!-- 编辑时 -->
<img
v-if="avaterUploadImg"
:src="avaterUploadImg"
class="avatar"
:style="{'width' : width, height: 'auto'}"
/>
<div v-if="avaterUploadImg && isNeedUpload" class="avatar-edit">
<div class="avatar-edit_magnifier" @click.stop="viewBigImg">
<svg-icon icon-class="ic-view" class="ic_edit"></svg-icon>
</div>
<span class="avatar-edit_line">|</span>
<div class="avatar-edit_replace" @click.stop="$refs['input'].click()">
<svg-icon :icon-class="editIconAndTitle.editIcon" class="ic_edit margin-right_8"></svg-icon>
<span>{{editIconAndTitle.editTitle}}</span>
</div>
</div>
<!-- 新增时的+ -->
<div
v-if="!avaterUploadImg && isNeedUpload"
class="avatar-uploader-icon"
@click.stop="$refs['input'].click()"
:style="{'width':width,'height':height}"
>
<i class="el-icon-plus"></i>
</div>
</div>
<slot name="tip"></slot>
<!-- 上传文件 -->
<input type="file" ref="input" @change="imageChange" :accept="accept" style="display:none;" />
<!-- 放大查看 -->
<el-image-viewer
v-if="showViewer"
:urlList="preViewSrcList"
:on-close="closeViewer"
:zIndex="2020"
></el-image-viewer>
</div>
</template>
引入
import elImageViewer from "element-ui/packages/image/src/image-viewer.vue";
<script>
import elImageViewer from "element-ui/packages/image/src/image-viewer.vue";
export default {
components: {
elImageViewer
},
props: {
viewImgTitle: {
// 默认为图片查看 有的话就是文字
type: String,
default: ""
},
isNeedUpload: {
// 是否需要上传 false的话 不能上传 只能点击放大
type: Boolean,
default: true
},
isBase64: {
// 返回出去的是否是base64字符串
type: Boolean,
default: false
},
editIconAndTitle: {
type: Object,
default: () => {
return {
editIcon: "ic-white-edit",
editTitle: "Edit"
};
}
},
uploadImg: {
// 开始传递的图片
default: ""
},
// 可以上传的类型
accept: {
type: String,
default: "image/png, image/jpeg, image/jepg"
},
width: {
type: String || Number,
default: "100%"
},
height: {
type: String || Number,
default: "100%"
},
// 没有图片时的错误提示
messageWarning: {
type: String,
default: "No image, please upload it first"
}
},
computed: {
fileSelecter() {
return this.$refs["input"];
}
},
data() {
return {
avaterUploadImg: "", // 组件存储的图片
showViewer: false,
preViewSrcList: []
};
},
watch: {
uploadImg: {
handler: function(newVal, oldVal) {
this.avaterUploadImg = newVal;
}
}
},
created() {
this.avaterUploadImg = this.uploadImg;
},
methods: {
// 上传/更改图片
imageChange($event) {
if ($event["target"]["files"].length === 0) return;
const selectFile = $event["target"]["files"][0];
let flag = this.beforeAvatarUpload(selectFile);
if (flag) {
this.avaterUploadImg = window.URL.createObjectURL(selectFile);
if (this.isBase64) {
// 将图片转换为base64 暴露出去
this.imageToBase64(selectFile).then(res => {
this.$emit("imageChange", res);
});
} else {
// 将图片暴露出去
this.$emit("imageChange", selectFile);
}
}
},
// 开启预览
viewBigImg(val) {
if (val === "img" && this.isNeedUpload) return; // 如果需要上传 点击图片 不放大
if (!this.avaterUploadImg) {
this.$message.warning(this.messageWarning);
return;
}
this.showViewer = true;
this.preViewSrcList = [this.avaterUploadImg];
window.document.body.style.overflow = "hidden";
this.$emit("viewBigImg");
},
// 关闭预览图片
closeViewer() {
this.showViewer = false;
this.preViewSrcList = [];
window.document.body.style.overflow = "auto";
this.$emit("closeViewer");
},
// 上传之前做校验
beforeAvatarUpload(file) {
const isFitFormats =
file.type === "image/png" ||
file.type === "image/jpeg" ||
file.type === "image/jepg";
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isFitFormats) {
this.$message.error(
"The uploaded image can only be in jpg/jpeg/png format"
);
}
if (!isLt5M) {
this.$message.error("The uploaded image size cannot exceed 5MB");
}
return isFitFormats && isLt5M;
},
imageToBase64(img) {
return new Promise((resolve, reject) => {
let reader = new FileReader(); //新建一个FileReader对象
reader.readAsDataURL(img); //将读取的文件转换成base64格式
reader.onload = function(e) {
resolve(e.target.result);
};
});
}
}
};
</script>
自定义调整样式
<style lang="less" scoped>
.image-picker {
display: inline-block;
.view-image-title {
cursor: pointer;
}
.avatar-uploader {
border: 1px dashed #d8dce6;
background-color: #ffffff;
border-radius: 6px;
line-height: 160px;
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
}
.avatar-edit {
width: 100%;
height: 32px;
background: rgba(0, 0, 0, 0.5);
border-radius: 0 0 4px 4px;
position: absolute;
bottom: 0;
left: 0;
color: #fff;
display: flex;
align-items: center;
line-height: 32px;
}
.avatar-edit_magnifier {
cursor: pointer;
width: 44px;
height: 32px;
}
.avatar-edit_line {
width: 5px;
height: 16px;
line-height: 16px;
}
.avatar-edit_replace {
flex: 1;
height: 100%;
cursor: pointer;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
.ic_edit {
width: 14px;
height: 14px;
vertical-align: middle;
}
.logo-reminder {
margin-top: 5px;
font-family: Helvetica;
font-size: 12px;
color: #606266;
line-height: 18px;
.logo-reminder_detail {
display: block;
margin: 0 auto;
width: 200px;
}
}
}
.avatar-uploader.avatar-uploader_border {
border: 1px solid #d8dce6;
background-color: #f5f7fa;
}
.margin-right_8 {
margin-right: 8px;
}
.cursor {
cursor: pointer;
}
/deep/.el-image-viewer__wrapper .el-image-viewer__canvas > img {
background-color: #f5f7fa;
}
/deep/.el-icon-circle-close{
color: #FFF
}
}
</style>
页面调用:例1 预览+上传
<el-form-item label="logo:" prop="logo">
<ImagePicker
:uploadImg="logo"
@imageChange="imageChange"
width="160px"
height="160px"
:isBase64="true"
key="add-logo"
>
<div
slot="tip"
class="upload-tip"
>Suport jpg/jpeg/png formats,the size should not exceed 5M.</div>
</ImagePicker>
</el-form-item>
例2: 预览不上传
//:editIconAndTitle="{'editIcon': 'ic-reupload', 'editTitle': 'Re-upload'}"
<ImagePicker
:uploadImg="obj['signature']"
:isNeedUpload="false"
class="margin-left-right_4"
width="160px"
height="160px"
key="patient-signature"
></ImagePicker>
imageChange(val) {
// 赋值
this.form["loge"] = val;
},