前言
項(xiàng)目中有個(gè)業(yè)務(wù)場(chǎng)景,有些業(yè)務(wù)用戶想要參與必須要獲取用戶手機(jī)號(hào),所以很多頁(yè)面都寫了獲取手機(jī)號(hào)的判斷和相關(guān)引導(dǎo)邏輯?代碼和樣式重復(fù)了很多次,針對(duì)這種場(chǎng)景,我們可以把獲取用戶手機(jī)號(hào)的效果頁(yè)面做成組件,減少代碼和維護(hù)量。
準(zhǔn)備工作
分析抽離的頁(yè)面代碼和js代碼和樣式和第三方組件,思考我們要哪些變量是從主頁(yè)傳到組件的,組件要拋出什么自定義事件給主頁(yè)面接收。
場(chǎng)景分析
小程序UI框架使用的是vant-weapp框架,獲取手機(jī)號(hào)的效果是,點(diǎn)擊某些按鈕或者進(jìn)入頁(yè)面onLoad時(shí)判斷用戶緩存中是否存在用戶是否存在手機(jī)號(hào),沒(méi)有就彈出一個(gè)彈窗,彈窗內(nèi)容提示用戶為什么要獲取手機(jī)號(hào),有取消和確定按鈕,取消則關(guān)閉彈窗,確定則觸發(fā)微信獲取手機(jī)號(hào)的函數(shù)bindgetphonenumber,然后請(qǐng)求后端接口解密、更新用戶數(shù)據(jù),然后返回最新的用戶信息。
開始
項(xiàng)目根目錄下創(chuàng)建空文件夾components,這個(gè)目錄是專門放組件的,然后在這個(gè)文件夾下創(chuàng)建自定義組件文件夾,準(zhǔn)備放組件用到的js、json、wxml、wxss等文件,比如我在components創(chuàng)建空文件夾getPhone文件夾,然后選擇getPhone文件夾右鍵-新建component,名稱是getPhone,這樣開發(fā)工具就可以幫忙生成初始文件了

抽離代碼部分我就不解釋那么多,直接上最后效果,自定義組件相關(guān)的大家可以先去看看官方文檔,理解一些關(guān)鍵字
組件部分
getPhone.js
// components/getPhone.js
var http = require("../../utils/http.js");
/* 獲取手機(jī)號(hào)的彈窗頁(yè)面,引導(dǎo)用戶點(diǎn)擊按鈕
----------------------------------------------- */
Component({
/**
* 組件的屬性列表
*/
properties: {
// code,在父組件通過(guò)wx.login獲取,不在組件中寫,避免重復(fù)請(qǐng)求
code: {
type: String,
value: ''
},
// 是否允許關(guān)閉彈窗,在有些頁(yè)面,是直接保持彈出手機(jī)號(hào)獲取框的,不允許用戶操作,強(qiáng)制獲取手機(jī)號(hào)
isCloseEvent:{
type: Boolean,
value: true
}
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
// 隱藏彈窗
empower: false
},
/**
* 組件的方法列表
*/
methods: {
// 組件初始化事件,比如父組件喚起子組件
eventInit() {
let that = this
that.setData({
empower: true
})
console.log(that.data)
},
//綁定手機(jī)號(hào)
getPhoneNumber: function (e) {
let that = this
e.wx_phone_code = that.properties.code
http.featPhone(e, function (userInfo) {
that.setData({
empower: false
})
// 成功則拋出自定義事件,參數(shù)是最新的用戶信息
that.triggerEvent('success', userInfo);
})
},
//拒絕綁定手機(jī)
popBtnN: function (e) {
// console.log(e)
if(this.properties.isCloseEvent){
this.setData({
empower: false
})
// 關(guān)閉彈窗是否觸發(fā)事件
}
},
}
})
getPhone.json
{
"component": true,
"usingComponents": {
"van-popup": "@vant/weapp/popup/index"
}
}
getPhone.wxml
<!--components/getPhone.wxml-->
<van-popup show="{{ empower }}" position="bottom" custom-class="bott_popup" bind:close="onClose">
<view class="flex-column content-around h-fill p-3">
<view class="flex-row align-center">
<image class="popup_logo" src="../../lib/img/my.png"></image>
<view class="font-medium ml-2">PayFun貝樂(lè)</view>
<text class="ml-2">申請(qǐng)</text>
</view>
<view class="flex-column">
<text class="font-medium">請(qǐng)求獲取手機(jī)號(hào)</text>
<text class="font-extra-small mt-2">如拒絕,將會(huì)影響預(yù)訂和購(gòu)買套餐功能的使用</text>
</view>
<view class="flex-row content-around">
<van-button type="default" custom-class="popup_btn1" bindtap="popBtnN">拒絕</van-button>
<button open-type="getPhoneNumber" class="phone_btn van-button van-button--primary"
bindgetphonenumber="getPhoneNumber">允許</button>
</view>
</view>
</van-popup>
getPhone.wxss
/* components/getPhone.wxss */
/* 手機(jī)窗 */
.bott_popup{
height: 220px;
background: #EDEDED;
}
.flex-column {
display: flex;
flex-direction: column;
}
.content-around {
justify-content: space-around;
}
.h-fill {
height: -webkit-fill-available;
}
.p-3 {
padding: 30rpx;
}
.flex-row {
display: flex;
flex-direction: row;
}
.align-center {
align-items: center;
}
.popup_logo {
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
/*小標(biāo)題*/
.font-medium {
font-size: 32rpx;
font-weight: bold;
}
.ml-2 {
margin-left: 20rpx;
}
/*輔助文字*/
.font-extra-small {
font-size: 26rpx;
color: #909399;
}
.mt-2 {
margin-top: 20rpx;
}
.popup_btn1 {
width: 250rpx;
}
.phone_btn {
width: 250rpx;
margin: 0;
position: relative;
display: -webkit-inline-flex;
display: inline-flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
padding: 0;
text-align: center;
vertical-align: middle;
-webkit-appearance: none;
-webkit-text-size-adjust: 100%;
height: 44px;
height: var(--button-default-height,44px);
line-height: 20px;
line-height: var(--button-line-height,20px);
font-size: 14px;
font-size: var(--button-default-font-size,14px);
transition: opacity .2s;
transition: opacity var(--animation-duration-fast,.2s);
border-radius: 2px;
border-radius: var(--button-border-radius,2px);
color: #fff;
color: var(--button-primary-color,#fff);
background: #07c160;
background: var(--button-primary-background-color,#07c160);
}
index.js
主頁(yè)面代碼部分,樣式也剝離了,所以主頁(yè)面代碼就沒(méi)有組件的樣式代碼了。
這里說(shuō)明下,在去觸發(fā)按鈕bindgetphonenumber函數(shù)前,必須獲取最新的code,這個(gè)code要拿去后端解密用的,如果你先執(zhí)行了bindgetphonenumber函數(shù),在獲取code,會(huì)導(dǎo)致code不一樣,執(zhí)行bindgetphonenumber函數(shù)時(shí)加密的code和你后面拿的code明顯不一樣,這里順序要對(duì)
// 習(xí)慣給默認(rèn)值
data: {
// wx.login拿到的code
wx_phone_code: ''
}
wx.login({
success(res) {
if (res.code) {
let code = res.code;
that.setData({
wx_phone_code: code
})
// 初始化獲取手機(jī)號(hào)組件
that.selectComponent('#componentsPhoneId').eventInit()
} else {
wx.showToast({
title: '微信授權(quán)登錄失敗',
icon: 'none',
duration: 2000//持續(xù)的時(shí)間
});
return;
}
}
}),
// 獲取手機(jī)號(hào)成功后回調(diào)事件
getPhoneSuccess:function(event){
if(event){
this.setData({
userinfo:event.detail
})
}
},
index.json
"usingComponents": {
"getPhone": "/components/getPhone/getPhone"
}
index.wxml
<!-- 獲取用戶手機(jī)號(hào)彈窗 -->
<getPhone id="componentsPhoneId" code="{{wx_phone_code}}" bind:success="getPhoneSuccess"></getPhone>
大概思路
拿到code后執(zhí)行that.selectComponent('#componentsPhoneId').eventInit(),就算執(zhí)行組件的eventInit方法,去顯示組件,組件拿到解密后的接口后拋出that.triggerEvent('success', userInfo);success事件名稱,userInfo參數(shù),然后主頁(yè)面bind:success="getPhoneSuccess" 監(jiān)聽事件success,并自定義事件getPhoneSuccess,userInfo的值是在event.detail里面,大家可以打斷點(diǎn)看看哈
最后效果,上圖
