vue3头像上传组件

这篇具有很好参考价值的文章主要介绍了vue3头像上传组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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文章来源地址https://www.toymoban.com/news/detail-431712.html

@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头像上传组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • vue3头像上传组件

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

    2024年02月02日
    浏览(26)
  • Vue3.2+TS的组件间的v-model传值

    组件之间的v-model,为什么可以v-model,大家可以去看看v-model的原理,然后就会发现这个方法一目了然。 父组件 子组件 假如子组件需要按照某个方法变化,那么可以自己定义,比如需要自增加50

    2024年02月13日
    浏览(45)
  • Vue3-在HTML标签、组件标签上使用v-model

    本篇为Vue3学习中遇到的v-model相关的记录,如有问题欢迎指正 v-model通常在input、select等标签上来实现数据双向绑定 原理 :v-model通过给标签value赋值来实现  数据—页面 的绑定。然后通过绑定input事件实现 页面—数据 的绑定。 原理 :在组件上时,v-model通过 :modelValue 来进行

    2024年01月24日
    浏览(59)
  • 【Vue技巧】Vue2和Vue3组件上使用v-model的实现原理

    ChatGPT4.0国内站点,支持GPT4 Vision 视觉模型:海鲸AI 在Vue中, v-model 是一个语法糖,用于在输入框、选择框等表单元素上创建双向数据绑定。当你在自定义组件中实现 v-model 功能时,你需要理解它背后的原理: v-model 实际上是一个属性和一个事件的简写。 在 Vue 2.x 中, v-mode

    2024年01月15日
    浏览(61)
  • 【vue3】10-vue组件化额外知识补充(下)-动态组件-组件缓存-v-model在组件上的应用

    切换组件案例: 比如我们现在想要实现了一个功能: 点击一个tab-bar,切换不同的组件显示; 这个案例我们可以通过两种不同的实现思路来实现: 方式一 :通过v-if来判断,显示不同的组件; 方式二 :动态组件的方式; 方式一代码示例: 动态组件方式实现 动态组件是使用 component组

    2024年02月08日
    浏览(66)
  • vue3 子组件上绑定(v-model=“xx“) 父组件传过来的值后报错

    vue3的项目中, 升级了vant的版本(^4.0.7)后, 子组件中用v-model的地方出现了报错 v-model cannot be used on a prop, because local prop bindings are not writable. Use a v-bind binding combined with a v-on listener that emits update:x event instead. 在阅读vue3的文档中看到了这么一段话 所有的 props 都遵循着单向绑定原则

    2024年02月04日
    浏览(72)
  • vue项目中对组件使用v-model绑定值,在vue3中如何更新数据

    在el-form 中 el-form-item 绑定组件进行校验 想在表单下面爆红提示 可以对组件使用v-model绑定值 vue2 通过this.$emit(‘input’,value) 更新 v-model值 vue3 通过this.$emit(‘update:modelValue’ ,value) 更新 v-model值

    2024年02月15日
    浏览(55)
  • vue3基础(五)watch(浅监听及深度监听),鼠标及键盘修饰符,v-model,对象写法,class使用数组,字符串模版,自定义组件标签上添加事件无效,使用data时用别名替代,solt输出内容

    监听中的 方法名 与 需要监听的 变量名 一致 如果没有(例如aa), 不会报错 ,但监听不到 所以上图会 输出1 ,而不会输出2 newValue改变后的值,oldValue改变前的值 watch 可以监听 computed 计算属性中的方法,变量等等 点击go按钮,调用change方法修改kk的值,computed中有kk,所以

    2024年02月15日
    浏览(57)
  • vue3 组件响应式v-model 失效,实践踩坑,一文搞懂组件响应式原理,对初学者友好

    vue3的v-model已经有了变化,假如你还不知道其中细节,看完这篇文章你就完全明白了,我以踩坑的场景来进行解析。起因是在我的项目中需要一个输入框组件,这个组件用来根据输入异步查询系统内已有人员,而且在多个地方需要用到这个输入框,所以必须要封装成组件,但

    2024年02月02日
    浏览(54)
  • 前端Vue篇之v-model 是如何实现的,语法糖实际是什么?v-model 可以被用在自定义组件上吗?如果可以,如何使用?

    v-model 在 Vue.js 中扮演着重要的角色,实现了表单输入和应用状态之间的双向数据绑定。其具体实现方式取决于所绑定元素的类型。 作用在表单元素上 : 当 v-model 用于表单元素(如 input、textarea)时,它动态绑定了 input 的 value 到指定的变量,并在触发 input 事件时动态更新这

    2024年04月28日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包