作者也是剛開始接觸小程序開發(fā)塘安,不足之處請(qǐng)指正卧斟。
先看工程目錄殴边,index、logs唆涝、mine找都、wallet這幾個(gè)文件夾可以看做一個(gè)個(gè)頁(yè)面,每個(gè)文件夾(頁(yè)面)里有四個(gè)文件:.js .json .wxml .wxss
.js文件就是JavaScript廊酣,寫邏輯相關(guān)的代碼
.json文件做一些固定的配置
.wxml類似于html寫控件
.wxss類似于css 寫控件的樣式
具體來看
創(chuàng)建一個(gè)小程序項(xiàng)目會(huì)默認(rèn)有app.js能耻,app.json,app.wxss這三個(gè)文件作用于是整個(gè)小程序亡驰,而每個(gè)頁(yè)面里的這幾個(gè)文件的作用域是當(dāng)前頁(yè)面晓猛。
先來看官方默認(rèn)創(chuàng)建的代碼
//app.js
App({
onLaunch: function () {
// 展示本地存儲(chǔ)能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登錄
wx.login({
success: res => {
// 發(fā)送 res.code 到后臺(tái)換取 openId, sessionKey, unionId
console.log('code',res)
}
})
// 獲取用戶信息
wx.getSetting({
success: res => {
console.log('setting',res.authSetting)
if (res.authSetting['scope.userInfo']) {
// 已經(jīng)授權(quán),可以直接調(diào)用 getUserInfo 獲取頭像昵稱凡辱,不會(huì)彈框
wx.getUserInfo({
success: res => {
// 可以將 res 發(fā)送給后臺(tái)解碼出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是網(wǎng)絡(luò)請(qǐng)求戒职,可能會(huì)在 Page.onLoad 之后才返回
// 所以此處加入 callback 以防止這種情況
if (this.userInfoReadyCallbacks) {
this.userInfoReadyCallbacks(res)
}
}
})
}
}
})
},
globalData: {
userInfo: null
}
})
onLaunch函數(shù)是小程序生命周期函數(shù),監(jiān)聽小程序初始化透乾。即小程序入口洪燥,通過查閱官方文檔可以看到此函數(shù)的解釋。
下面來分析 var logs = wx.getStorageSync('logs') || []乳乌,wx.調(diào)用的wx.getStorageSync一看就是微信官方API捧韵,這行代碼是同步獲取key為'logs'的緩存,且logs變量類型為數(shù)組汉操。通過查閱官方API可以看到此函數(shù)的定義再来,同步獲取緩存也就是會(huì)阻塞當(dāng)前線程的意思嘍,即獲取完這個(gè)數(shù)組才會(huì)繼續(xù)執(zhí)行代碼。
logs.unshift(Date.now())又是啥意思呢芒篷,查詢微信官方API發(fā)現(xiàn)unshift方法是ES5標(biāo)準(zhǔn)里的搜变,意思是在數(shù)組的最前面插入一個(gè)元素,這里是插入了當(dāng)前時(shí)間戳针炉。
wx.setStorageSync('logs', logs)從字面看就是同步保存這個(gè)被修改的數(shù)組到緩存中挠他。
// 登錄
wx.login({
success: res => {
// 發(fā)送 res.code 到后臺(tái)換取 openId, sessionKey, unionId
console.log('code',res)
}
})
這個(gè)wx.login是什么意思,wx.開頭即微信提供的API篡帕,意思是調(diào)用了login接口獲取登錄憑證(code)绩社,調(diào)用成功即success會(huì)返回code,然后向我們自己的服務(wù)器請(qǐng)求換取openId, sessionKey, unionId這些信息赂苗,來進(jìn)行登錄操作。
// 獲取用戶信息
wx.getSetting({
success: res => {
console.log('setting',res.authSetting)
if (res.authSetting['scope.userInfo']) {
// 已經(jīng)授權(quán)贮尉,可以直接調(diào)用 getUserInfo 獲取頭像昵稱拌滋,不會(huì)彈框
wx.getUserInfo({
success: res => {
// 可以將 res 發(fā)送給后臺(tái)解碼出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是網(wǎng)絡(luò)請(qǐng)求,可能會(huì)在 Page.onLoad 之后才返回
// 所以此處加入 callback 以防止這種情況
if (this.userInfoReadyCallbacks) {
this.userInfoReadyCallbacks(res)
}
}
})
}
}
})
wx.getSetting用來獲取小程序已經(jīng)向用戶請(qǐng)求過的權(quán)限猜谚,返回形式是一個(gè)字典(key:value)形式败砂,其中'scope.userInfo'就是獲取用戶信息的key,如果這項(xiàng)為true就是獲取到用戶信息的意思。
wx.getUserInfo用來獲取用戶信息魏铅,success就會(huì)返回用戶信息
this.globalData.userInfo = res.userInfo昌犹,this類似于iOS開發(fā)中的self,globalData是自定義的一個(gè)全局變量览芳,內(nèi)部數(shù)據(jù)結(jié)構(gòu)是有一個(gè)userInfo斜姥,用來全局保存用戶信息。
this.userInfoReadyCallbacks又是個(gè)什么呢沧竟,類似于iOS開發(fā)中的block(閉包),函數(shù)名隨便取铸敏,我就在后面加了個(gè)s, 用來異步反向傳值,因?yàn)閣x.getUserInfo這個(gè)接口是異步獲取的悟泵,有可能會(huì)在index的js里的onLoad方法之后返回杈笔,如果index頁(yè)面調(diào)用了userInfoReadyCallbacks來接收userInfo數(shù)據(jù),則app.js里會(huì)執(zhí)行this.userInfoReadyCallbacks(res)糕非,就可以異步給index頁(yè)面?zhèn)髦盗恕?/p>
//index.js
app.userInfoReadyCallbacks = res => {
if (res.userInfo) {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
}
下面來看index.js文件
//index.js
//獲取應(yīng)用實(shí)例
const app = getApp()
Page({
data: {
motto: '尬先生尬先生尬先生尬先生尬先生尬先生尬先生尬先生',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')//固定寫法 通過button獲取用戶信息只能這么寫
},
//事件處理函數(shù)
bindViewTap: function () {//點(diǎn)擊頭像跳轉(zhuǎn)logs頁(yè)面
wx.navigateTo({
url: '../logs/logs'
})
},
onLoad: function () {
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
} else if (this.data.canIUse) {
// 由于 getUserInfo 是網(wǎng)絡(luò)請(qǐng)求蒙具,可能會(huì)在 Page.onLoad 之后才返回
// 所以此處加入 callback 以防止這種情況
app.userInfoReadyCallbacks = res => {
if (res.userInfo) {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
}
} else {
// 在沒有 open-type=getUserInfo 版本的兼容處理
wx.getUserInfo({
success: res => {
if (res.userInfo) {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
}
})
}
},
getUserInfoClick: function (e) {//點(diǎn)擊了拒絕或同意后會(huì)回調(diào)
if (e.detail.userInfo) {
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
}
})
const app = getApp()獲取應(yīng)用實(shí)例,這樣就可以使用全局變量了朽肥。
data: {
motto: '尬先生尬先生尬先生尬先生尬先生尬先生尬先生尬先生',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')//固定寫法 通過button獲取用戶信息只能這么寫
},
定義了一個(gè)名為data的數(shù)據(jù)結(jié)構(gòu)禁筏,有四個(gè)元素motoo是一個(gè)字符串,userInfo用戶信息鞠呈,hasUserInfo是否獲取到了用戶信息bool類型融师,canIUse判斷小程序的API,回調(diào)蚁吝,參數(shù)旱爆,組件等是否在當(dāng)前版本可用舀射,當(dāng)前是判斷button里獲取用戶信息在當(dāng)前版本是否可用,'button.open-type.getUserInfo'就是通過button獲取用戶信息的固定寫法怀伦。
bindViewTap: function () 是在index.wxml里綁定的頭像image點(diǎn)擊事件脆烟,即登錄以后點(diǎn)擊頭像進(jìn)行后續(xù)操作。
wx.navigateTo({
url: '../logs/logs'
})
wx.navigateTo保留當(dāng)前頁(yè)面房待,跳轉(zhuǎn)到應(yīng)用內(nèi)的某個(gè)頁(yè)面邢羔,url: '../logs/logs'即跳轉(zhuǎn)到logs頁(yè)面
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
}
如果在app.js頁(yè)面獲取userInfo速度快于index.js的onLoad方法,走這里桑孩。 this.setData給data賦值的同時(shí)會(huì)主動(dòng)刷新index.wxml里的UI數(shù)據(jù)拜鹤。
getUserInfoClick: function (e) {//點(diǎn)擊了拒絕或同意后會(huì)回調(diào)
if (e.detail.userInfo) {
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
}
getUserInfoClick是在index.wxml里綁定的bindgetuserinfo="getUserInfoClick"即button的點(diǎn)擊以后彈出的權(quán)限授權(quán)框的點(diǎn)擊事件回調(diào)。
下面看下index.wxml文件
<!--index.wxml-->
<view class="container">
<view class="userinfo">
<button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfoClick"> 獲取頭像昵稱 </button>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>
<view>標(biāo)簽視圖容器流椒,class="container"敏簿,給這個(gè)view起個(gè)名字,方便在index.wxss文件里給這個(gè)標(biāo)簽設(shè)置樣式宣虾。
<button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfoClick"> 獲取頭像昵稱 </button>
<button>標(biāo)簽惯裕,wx:if="{{!hasUserInfo && canIUse}}"如果同時(shí)滿足!hasUserInfo && canIUse這兩個(gè)條件則繪制這個(gè)button,open-type="getUserInfo"意思是這個(gè)button點(diǎn)擊后用來請(qǐng)求用戶信息是固定寫法绣硝。bindgetuserinfo="getUserInfoClick"綁定一個(gè)名為getUserInfoClick的函數(shù)作為授權(quán)彈窗的回調(diào)方法蜻势。
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
<block>如果要一次性判斷多個(gè)組件標(biāo)簽,可以使用一個(gè) <block/> 標(biāo)簽將多個(gè)組件包裝起來鹉胖,這里包裝了一個(gè)<image>和一個(gè)<text>標(biāo)簽握玛。
{{userInfo.nickName}}包裹變量用兩個(gè)花括號(hào)包裝起來。