1.布局
<template>
<div class="box">
<img :src="avatar" alt="" />
<input type="file" style="display: none" ref="iptRef" @change="onFileChange" /><br /><br />
<button style="margin-right: 30px" @click="chooseImg">选择图片</button> <button>上传头像</button>
</div>
</template>
2.开始实现功能
// 选择图片->点击事件
chooseImg() {
// 目的:为了让input[type=file]标签,让他再用JS代码来触发他的点击事件(导致他默认行为给一个文件选择窗口)
// 原因:input[type=file]他是原生的html标签,样式不太好改
// 解决:用display:none将他隐藏,然后用其他事件来触发他的点击事件click(),类似于移花接木
this.$refs.iptRef.click()
},
// 选择图片确定了
onFileChange(e) {
// 原生事件对象
const files = e.target.files // 拿到用户选择的文件数组
}
3.转换方式
if (files.length === 0) {
// 证明刚刚文件选择窗口打开了,但是他一个文件都没选择然后点击了确定关闭选择弹窗
} else {
// 证明了他选择了文件(默认只能选1个,如果选择多个需要给input加上而外的原生属性)
console.log(files[0])
// 目标:选择的图片文件,要给到img标签上做到纯前端的预览
// img标签的src值
// * 只能是图片的"链接地址"(外链http://开头,图片文件相对路径)
// * 或者是图片的base64字符串(而且字符串还必须要data:img/png;base64,图片转base64字符串)
// 解决方案1:文件->内存临时地址(这个地址只能在js里内存里不能发给后台)
// 语法:URL.createObjectURL(文件)
// 返回值:内存临时地址
// this.avatar = URL.createObjectURL(files[0])
// 解决方案2:文件-> base64字符串(此字符串是可以发给后台的)
const fr = new FileReader()
fr.readAsDataURL(files[0]) // 传入文件对象开始读
fr.onload = (e) => {
// onload等待把文件都城base64字符串后触发onload事件函数
// e.target.result的值就是读完的结果
this.avatar = e.target.result // 赋给变量让他显示在img的src里
}
}