vue3 头像上传 组件功能实现

 更新时间:2023年05月18日 08:23:19   作者:ps酷教程  
这篇文章主要介绍了vue3头像上传组件功能,用到了自定义组件v-model的双向绑定,使用axios + formData 上传文件,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下

vue3 头像上传 组件功能

在这里插入图片描述

  • 用到了自定义组件v-model的双向绑定
  • 使用input的type=file这个原生html元素,通过监听change事件,获取到选择的文件(注意,选择完文件值后,要把这个隐藏的input的type=file元素的value置为空,否则,下次选择同样的图片,将不会触发change事件)
  • 使用axios + formData 上传文件
  • 后台做保存文件,以及静态资源目录映射即可

前端

AvatarUpload.vue

<template>
    <div class="avatar-upload-wrapper">
        <!-- {{ modelValue }} -->
        <div :class="['avatar-box',{'avatar-box-border':imgUrl?false:true}]" @click="clickAvatarBox" :style="{width: size + 'px',height: size + 'px'}">
        	<!-- 隐藏的input的type=file -->
            <input type="file" hidden ref="fileInputRef" accept="image/x-png,image/gif,image/jpeg,image/bmp" @change="changeFile">
            <img v-if="imgUrl" :src="imgUrl" alt="">
            <div v-else class="avatar-marker">
                <i class="iconfont icon-jiahao"></i>
            </div>
        </div>
    </div>
</template>
<script setup>
    import Messager from '@/utils/messager'
    import axiosInstance from '@/utils/request'
    import { ref,reactive,watch } from 'vue'
    const emits = defineEmits(['update:modelValue'])
    const props = defineProps({
        size: {
            type: Number,
            default: 64
        },
        modelValue: {
            type: String,
            default: '' // 默认头像链接地址
        },
        maxSize: {
            type:Number,
            default: 5 // 默认最大不超过5M
        },
        serverUrl: {
            type:String,
            default: 'http://localhost:9091/static/img'
        } 
    })
    const fileInputRef =ref(null)
    // const imgUrl = ref('http://localhost:9091/static/img/avatar/3026520210706112210298.png')
    const imgUrl = ref(props.modelValue)
    // console.log(imgUrl.value);
    // 监听头像url改变(打开弹框时, 传入的图片地址变化时, 同步修改imgUrl)
    watch(()=>props.modelValue,(newVal,oldVal)=>{
        imgUrl.value = newVal
    })
    function clickAvatarBox() {
        fileInputRef.value.click()
    }
    function changeFile() {
        console.log(123,fileInputRef.value.files[0].size);
        // 获取更改后的文件
        let file = fileInputRef.value.files[0]
        // 校验文件大小
        if(file.size / 1024 / 1024 > props.maxsize) {
            Messager.error('文件超过指定大小')
        } 
        // 执行文件上传
        let formData = new FormData()
        formData.append("mfile", file)
        formData.append("type", "avatar")
        let config = {
            headers: {
                'Content-Type': 'multipart/form-data',
                'a':'b' // 随便自己带个什么请求头
            }
        } // 这个config可以不必携带, 当使用FormData传参时, 
          // axios会自己带上'Content-Type': 'multipart/form-data',请求头
        axiosInstance.post('/file/uploadFile',formData,config ).then(res=>{
            console.log(res,'上传成功');
            imgUrl.value = props.serverUrl + res
            let img = new Image()
            img.src = imgUrl.value
            img.onload = ()=>{
                emits('update:modelValue', imgUrl.value)
            }
        })
    }
</script>
<style lang="scss" scoped>
    .avatar-box-border {
        border: 1px dashed #409eff !important;
    }
    .avatar-box {
        border-radius: 50%;
        margin-left: 20px;
        cursor: pointer;
        position: relative;
        border: 2px solid #eee;
        overflow: hidden;
        &:hover::before {
            content:'';
            display: block;
            position: absolute;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,.03);
        }
        img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        .avatar-marker {
            position: absolute;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #409eff;
            i.iconfont {
                font-size: 24px;
            }
        }
    }
</style>

使用AvatarUpload.vue

<el-dialog v-model="userDialogVisible" width="450">
   <el-form :model="userForm" :rules="userFormRules" label-width="80">
        <el-form-item label="昵称" prop="nickname">
            <el-input v-model="userForm.nickname" style="width: 300px;"></el-input>
        </el-form-item>
        <!-- 使用头像上传组件 -->
        <el-form-item label="头像" prop="avatar">
            <avatar-upload v-model="userForm.avatar" />
        </el-form-item>
        <el-form-item label="个性签名" prop="bio">
            <el-scrollbar>
                <el-input type="textarea" :rows="3" v-model="userForm.bio" style="width: 300px;"></el-input>
            </el-scrollbar>
        </el-form-item>
        <el-form-item label="网站链接" prop="website">
            <el-input v-model="userForm.website" style="width: 300px;"></el-input>
        </el-form-item>
        <el-form-item label="是否可用" prop="disabled">
            <el-switch v-model="userForm.disabled" :active-value="0" :inactive-value="1" active-color="#13ce66"
                inactive-color="#eaecf0">
            </el-switch>
        </el-form-item>
        <el-form-item>
            <div style="margin-left: auto;">
                <el-button @click="userDialogVisible = false">取消</el-button>
                <el-button type="primary" @click="handleSave">确定</el-button>
            </div>
        </el-form-item>
    </el-form>
</el-dialog>

后端

上传接口

@PostMapping("uploadFile")
public Result<String> uploadFile(@RequestParam("mfile") MultipartFile mfile, String type) {
    return Result.ok(fileService.saveFile(mfile,type));
}
@Override
public String saveFile(MultipartFile mfile, String type) {
    String filePath = FilePathEnum.type(type).getPathPrefix() + SnowflakeIdWorker.generateId().substring(0, 8) + mfile.getOriginalFilename();
    String targetFilePath = fileSavePath + filePath;
    try {
        mfile.transferTo(new File(targetFilePath));
    } catch (IOException e) {
        throw BizException.SAVE_FILE_ERR;
    }
    return filePath;
}

配置mvc

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("file:D:\\Projects\\boot-blog\\src\\main\\resources\\static\\");
    }
}

到此这篇关于vue3 头像上传 组件的文章就介绍到这了,更多相关vue3 头像上传 组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue-ANTD表单输入中自定义校验一些正则表达式规则介绍

    Vue-ANTD表单输入中自定义校验一些正则表达式规则介绍

    这篇文章主要介绍了Vue-ANTD表单输入中自定义校验一些正则表达式规则介绍,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • vue使用高德地图实现添加点标记和获取点击位置信息的示例代码

    vue使用高德地图实现添加点标记和获取点击位置信息的示例代码

    这篇文章主要介绍了vue使用高德地图实现添加点标记和获取点击位置信息的示例代码,文中补充介绍了高德vue-amap使用(一)标记点位获取地址及经纬度,本文结合示例代码给大家介绍的非常详细,需要的朋友参考下吧
    2024-01-01
  • Vue ElementUI之Form表单验证遇到的问题

    Vue ElementUI之Form表单验证遇到的问题

    这篇文章主要介绍了Vue ElementUI之Form表单验证遇到的问题,需要的朋友可以参考下
    2017-08-08
  • vue中的cookies缓存存值方式 超简单

    vue中的cookies缓存存值方式 超简单

    这篇文章主要介绍了vue中的cookies缓存存值方式,超简单!具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • vue界面发送表情的实现代码

    vue界面发送表情的实现代码

    这篇文章主要介绍了vue界面发送表情的实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • vue样式叠层z-index不起作用的解决方案

    vue样式叠层z-index不起作用的解决方案

    这篇文章主要介绍了vue样式叠层z-index不起作用的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • Vue使用el-input自动获取焦点和二次获取焦点问题及解决

    Vue使用el-input自动获取焦点和二次获取焦点问题及解决

    这篇文章主要介绍了Vue使用el-input自动获取焦点和二次获取焦点问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • vue 实现LED数字时钟效果(开箱即用)

    vue 实现LED数字时钟效果(开箱即用)

    这篇文章主要介绍了vue 实现LED数字时钟效果(开箱即用),每一个数字由七个元素构成,即每一个segment元素,本文给大家分享实现实例,感兴趣的朋友一起看看吧
    2019-12-12
  • vue-cli 介绍与安装

    vue-cli 介绍与安装

    这篇文章主要给大家介绍的是vue-cli 介绍与安装,vue-cli是和vue进行深度组合的工具,可以快速帮我们创建vue项目,并且把一些脚手架相关的代码给我们创建好。真正使用vue开发项目,都是用vue-cli来创建项目的,下面文章详细内容,需要的朋友可以参考一下
    2021-10-10
  • Vue中实现3D标签云的详细代码

    Vue中实现3D标签云的详细代码

    本文通过实例代码给大家介绍vue实现3D标签云的方法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2021-07-07

最新评论