@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