天天看點

vue項目中實作頭像上傳的功能型元件功能需求

@vue項目中實作頭像上傳的功能型元件

功能需求

實作個人中心的頭像上傳功能:

1、使用者未上傳過頭像,展示設定好的預設頭像(區分男女)

2、支援格式png、jpg、jpeg

3、圖檔大小:小于等于2M

4、個人中心頭像上傳成功需要實作與項目導航欄頭像的關聯效果

5、不符合規則加入對應的吐司提示

需求分析

1、因為有展示預設頭像的需求,是以需要判斷使用者是否上傳過頭像,由接口擷取使用者個人資訊并将頭像資訊儲存在vuex,在前端頁面通過計算屬性映射vuex裡的頭像資料加以判斷。

2、在選擇檔案的回調函數中做格式,大小的判斷。根據具體情況做吐司提示效果(本文的吐司屬于自開發吐司元件,element ui等皆有提供類似功能,根據具體業務需求開發)

3、因為我們的頭像資料存放在vuex中,是以我們隻需要在上傳成功的時候把vuex裡的頭像資料改為上傳成功接口傳回的頭像路徑,導航欄的頭像資料來源為vuex,就能實作上傳頭像和導航欄的關聯效果

開發流程

1、在頁面的生命周期函數裡發起個人資訊請求,拿到頭像資料放在vuex裡

2、在上傳頭像元件的計算屬性裡擷取vuex裡的頭像資料,判斷是預設頭像(如果是預設頭像,還需卻要性别資訊老判斷男女)還是自定義頭像

3、使用input标簽實作上傳檔案的功能

廢話不多講,上代碼

<template>
    <div class="teacherInfohBox">
        <div class="avatarW" v-if="!avatar">  //此處為預設頭
            <img v-if="userGenderCode == 'UA01' " src="../../assets/img/setting/02_03.png" alt="">
            <img v-if="userGenderCode == 'UA02' " src="../../assets/img/setting/01_03.png" alt="">
        </div>
        <div class="avatarW" v-if="avatar">  //此處為自定義頭像
            <img :src="avatar" alt="">
        </div>
        <span @click="uploadHeadImg">更換頭像</span>
        <input
            type="file"
            accept="image/jpeg, image/jpg, image/png"  //使用者打開檔案選擇框預設展示的檔案格式,其他格式的檔案會做隐藏,但使用者仍能選擇,是以在上傳的時候得做二次驗證
            @change.stop="handleFile"  //回調函數
            class="hiddenInput"
        >
    </div>
</template>


<script>
import { mapState , mapActions ,mapMutations } from 'vuex';
const OSS = require('ali-oss');  //引入oss
export default {
    data() {
        return {
            avatarUrl:null //本地頭像路徑
        }
    },
    methods: {
        uploadHeadImg(){ //點選上傳頭像按鈕的事件
            this.$el.querySelector(".hiddenInput").click()  //事件轉移
        },
        handleFile(e) { //上傳頭像的事件函數
            this.$store.dispatch('getOssInfo',{type:"avatar"}).then(() => {  //先擷取oss檔案上傳的通行證
                var client = new OSS({  //構造oss
                    region:this.ossInfo.region,
                    accessKeyId:this.ossInfo.accessKeyId,
                    accessKeySecret:this.ossInfo.accessKeySecret,
                    stsToken:this.ossInfo.securityToken,
                    bucket:this.ossInfo.atchBucket
                })
                let $target = e.target || e.srcElement;
                let file = $target.files[0];
                var reader = new FileReader();  //圖檔渲染所需
                if(file){ //限制上傳檔案的大小
                    let size = 2*1024*1024  //檔案限制的大小
                    let type = file.type.split('/')[1]  //上傳檔案的格式
                    let name = this.ossInfo.atchRemoteDirPath + '/' + file.name  //上傳頭像的格式
                    if(file.size > size){
                        this.$toast.warning("大小超出限制")
                    }else if(type != 'png' && type != 'jpeg' && type != 'jpg'){
                        this.$toast.warning("圖檔格式不正确")
                    }else{
                        client.put(name,file).then((res) => { //這是往oss傳圖檔之後成功的回調
                            this.avatarUrl = res.url.substring(7,)
                            this.upLoadAvatar({     //往服務端發上傳頭像的請求
                                atchFmt: file.type.split('/')[1],
                                atchRemotePath: res.name,
                                atchBucket: this.ossInfo.atchBucket,
                                atchSize: file.size
                            }).then(() => {
                                this.$toast.success("上傳成功")
                                this.setAvatar(this.avatarUrl) //更改vuex裡的頭像資料
                                reader.readAsDataURL(file); //這裡需要考慮情況是否是點選更換頁面就變頭像,還是先調上傳頭像接口,待接口傳回成功後再改變頁面上的頭像
                            })
                        }).catch((err) => {
                            console.log("err")
                        })
                    }
                }
            })
        },
        ...mapMutations(['setAvatar']),  //vuex裡修改頭像路徑的同步方法
        ...mapActions(['upLoadAvatar'])  //調用後端上傳頭像的接口的異步方法
    },
    computed: {
        ...mapState({ //擷取個人中心的使用者性别
            userGenderCode:state => state.set.userList.userGenderCode,  //擷取使用者資訊,主要輸頭像和性别資訊
            ossInfo:state => state.set.ossInfo,  //擷取oss配置資訊
            avatar:state => state.set.avatar  //擷取頭像資訊
        })
    }
}
</script>

<style lang="scss" scoped>
@import "../../assets/css/_tools.scss";
.teacherInfohBox{
    height: 236px;
    text-align: center;
    @include por;
    .hiddenInput {
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        display: none;
        @include poa;
    }
    &>span{
        font-size: 10px;
        top: 10px;
        left: 475px;
        text-decoration: underline;
        @include c9;
        @include poa;
        @include finger;
    }
    .avatarW{
        left: 50%;
        transform: translate(-50%);
        margin-top:20px;
        width: 107px;
        height: 107px;
        border: 1px solid #33b6ae;
        border-radius: 50%;
        display: flex;
        justify-content: center;
        align-items: center;
        @include poa;
        img{
            height: 92px;
            width: 92px;
            border-radius: 50%;
        }
    }
}
</style>
           

##附oss對象存儲SDK連結:https://help.aliyun.com/document_detail/64041.html?spm=a2c4g.11186623.2.15.37ec15cdNTBg6r#concept-64041-zh