场景实现选取本地图片,到预览然后调用后台上传头像接口,再更新vuex

 

这是效果图

一步html模块

<template>
    <div>
        <el-card class="box-card">
            <div slot="header" class="clearfix"&gt;
                <span&gt;更换头像</span&gt;
            </div>

            <div>
                <!-- 图片用来展示用户选择的头像 -->
                <img v-if="!avatar" src="../../assets/images/body-bg.jpg" alt="" class="the_img" />
                <img v-else :src="avatar" alt="" class="the_img" />

                <!-- 按钮区域 -->
                <div class="btn-box">
                    <input type="file" accept="image/*" style="display:none;" ref="iptRef" @change="onFileChange">
                    <el-button type="primary" icon="el-icon-plus" @click="chooseImg">选择图片</el-button>
                    <el-button type="success" icon="el-icon-upload" :disabled="avatar===''" @click="uploadFn">上传头像</el-button>
                </div>
            </div>
        </el-card>
    </div>
</template>

第二步js模块

<script>
import { updateUserAvatarApi } from '@/api'// 导入更新头像的接口
export default {
  nameL: 'userAvatar',
  data () {
    return {
      avatar: '' // 用来保存图片链接/或者base64字符串地址
    }
  },
  methods: {
    chooseImg () { // 选择图片-点击事件
      // 目的:为了让input[type=file]标签,让他再用JS代码触发它的点击事件(导致它默认行为一个文件选择窗口)
      // 原因input[type=file]它是原生标签样式不太好改
      // 解决:移花接木
      this.$refs.iptRef.click()// 模拟 input[type=file] 的点击行为
    },
    onFileChange (e) { // 选择图片确定const files = e.target.files// 拿到用户选择的文件数组
      console.log('用户选择的文件数组:', files[0])
      if (files.length === 0) { // 说明文件选择的窗口打开了,但是它一个文件都没选择就点击确定关闭了选择弹框

      } else { // 证明选择了文件默认只能选择一个文件,如果选择多个需要input标签额外原生属性console.log('用户选择的文件数组:', files[0])
        // 目标:选择图片文件,要给到img标签上做纯前端预览
        // 知识点img标签src值
        //  只能是图片链接地址外链http://开头,或者图片相对路径)
        //  或者是图片的base64字符串(而且字符串必须是dataimage/pngbase64,图片转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里
        }
      }
    },
    uploadFn () { // 开始上传头像
      updateUserAvatarApi({ avatar: this.avatar }).then(res => {
        if (res.data.code === 0) {
          this.$message.success('更新成功!')
          this.$store.dispatch('upUserInfo')// 调用vuex中的方法,进而更新头像
        } else {
          this.$message.error('更新失败!')
        }
      })
    }
  }
}
</script>

完整代码:

<template>
    <div>
        <el-card class="box-card">
            <div slot="header" class="clearfix">
                <span>更换头像</span>
            </div>

            <div>
                <!-- 图片、用来展示用户选择的头像 -->
                <img v-if="!avatar" src="../../assets/images/body-bg.jpg" alt="" class="the_img" />
                <img v-else :src="avatar" alt="" class="the_img" />

                <!-- 按钮区域 -->
                <div class="btn-box">
                    <input type="file" accept="image/*" style="display:none;" ref="iptRef" @change="onFileChange">
                    <el-button type="primary" icon="el-icon-plus" @click="chooseImg">选择图片</el-button>
                    <el-button type="success" icon="el-icon-upload" :disabled="avatar===''" @click="uploadFn">上传头像</el-button>
                </div>
            </div>
        </el-card>
    </div>
</template>

<script>
import { updateUserAvatarApi } from '@/api'// 导入更新头像的接口
export default {
  nameL: 'userAvatar',
  data () {
    return {
      avatar: '' // 用来保存图片链接/或者base64字符串地址
    }
  },
  methods: {
    chooseImg () { // 选择图片-点击事件
      // 目的:为了让input[type=file]标签,让他再用JS代码来触发它的点击事件(导致它默认行为给一个文件选择窗口)
      // 原因input[type=file]它是原生标签,样式不太好改
      // 解决:移花接木
      this.$refs.iptRef.click()// 模拟 input[type=file] 的点击行为
    },
    onFileChange (e) { // 选择图片确定const files = e.target.files// 拿到用户选择的文件数组
      console.log('用户选择的文件数组:', files[0])
      if (files.length === 0) { // 说明文件选择的窗口打开了,但是它一个文件都没选择就点击了确定关闭了选择弹框

      } else { // 证明选择了文件(默认只能选择一个文件,如果选择多个,需要input标签加额外原生属性console.log('用户选择的文件数组:', files[0])
        // 目标:选择图片文件,要给到img标签上做纯前端预览
        // 知识点:img标签的src值
        //  只能是图片的链接地址(外链http://开头,或者图片的相对路径)
        //  或者是图片的base64字符串(而且字符串必须是data:image/pngbase64,图片转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里
        }
      }
    },
    uploadFn () { // 开始上传头像
      updateUserAvatarApi({ avatar: this.avatar }).then(res => {
        if (res.data.code === 0) {
          this.$message.success('更新成功!')
          this.$store.dispatch('upUserInfo')// 调用vuex中的方法,进而更新头像
        } else {
          this.$message.error('更新失败!')
        }
      })
    }
  }
}
</script>

<style scoped>
    .btn-box{margin-top:10px;}
    .preview{object-fit:cover;}
    .the_img{width:350px;height:350px;}
</style>

原文地址:https://blog.csdn.net/qq_17211063/article/details/128438949

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_37550.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注