前端篇-更换用户图片

145 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

更换用户图片在vue项目中是非常常见的,该篇文章带来的是前端篇

项目实现

API

api/index.js下新建更换头像的API

// 更新用户头像
export const UpdateAvatarAPI = data =>
  axios({
    url: '/my/update_avatar', // 路径
    method: 'POST', // 请求方式
    headers: { // 请求头
        'Content-Type': 'multipart/form-data'
    },
    data // 请求体
  })

html

  • 由于原生更换头像input样式比较丑,且比较难改
  • 一般都是自己写一个div样式,再隐藏原生的
  • 当点击div时,用js中的click()方法点击原生input
<div class="item" @click="clickAvatarFn">
  <input type="file" v-show="false" ref="iptAvatarRef" @input="editAvatarFn">
    <span>头像</span>
    <div class="item-content"><img :src="userinfo.user_pic" alt=""></div>
    <van-icon name="arrow" />
</div>

script

  • 图片的上传,一般都是以表单元素上传
  • FormData对象,就是用于异步上传二进制文件
  • e.target.files 是个数组, 长度大于0时代表用户选中了图片,反之用户没有选择图片
// 点击头像
clickAvatarFn () {
  this.$refs.iptAvatarRef.click() // 通过ref拿到input节点
},
// 编辑头像
async editAvatarFn (e) {
  const file = e.target.files // e.target.files 是个数组
  if (file.length > 0) { // file.length > 0代表选了图片,反之就是没选图片
    const fd = new FormData() // 表单元素
    fd.append('avatar', file[0]) // file[0] 文件对象, 'avatar' 是key名
    const { data: res } = await UpdateAvatarAPI(fd)
    if (res.status !== 200) return this.$notify({ type: 'danger', message: res.message }) // res.status判断头像是否上传成功
    this.$notify({ type: 'success', message: '更新图片成功' }) // this.$notify是vant组件库中的消息通知组件
    const { data: res1 } = await getMyInfoAPI() // getMyInfoAPI获取用户信息的API,用于刷新页面
    this.$store.commit('qq/UpdateUserInfo', res1.data) // 将最新值提交的vuex中
  }
}

前端预览图片的两种方式

  • 使用方式一的createObjectURL可以节省性能并更快速,只不过需要在不使用的情况下手动释放内存
  • 如果不太在意设备性能问题,并想获取图片的base64,则推荐方式二FileReader.readAsDataUR

方式一

  • createObjectURL是同步执行
  • 这种方式只能在本机使用
  • file[0]是文件对象,因为上面已经写了,所以就不再写判断了
const avatar = URL.createObjectURL(file[0]) // 临时地址,只能在本机使用

方式二

  • FileReader.readAsDataURL是异步执行
  • avatar结果是一个base64格式的图片,所以不局限于本机,其他地方也可以使用
const fr = new FileReader() 
fr.readAsDataURL(file[0]) // file[0]文件对象
fr.onload = e => { // onload等待把文件读成base64字符串后会触发onload事件函数 
    const avatar = e.target.result // e.target.result的值就是读完的结果 
}