文章為實戰(zhàn)中踩坑經(jīng)歷,以及解決方案。同時是自己的一個項目回顧,在這里分享給大家,希望能幫助到大家。文章內(nèi)代碼需要左右滑動噢~
登錄授權(quán)
授權(quán)(基本信息,手機號碼 )必須使用小程序原生的的button組件,然后指定open-type 后通過回調(diào)才能拿到用戶信息。代碼入下:
index.wxml
<view class="authorization" wx:if="{{!getUserInfo}}">
<view class="clue">你還未登錄,請先授權(quán)登錄</view>
<button open-type="getUserInfo" lang="zh_CN" bindgetuserinfo="bindGetUserInfo">
授權(quán)登錄
</button>
</view>
<view class="authorization" wx:if="{{getUserInfo && !getPhone}}">
<view class="clue">你還未綁定手機號,請先去綁定</view>
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">
立即綁定
</button>
</view>
index.js
page({
// ...
data: {
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
userInfo: {},
getUserInfo: false,
getPhone: false,
hasAuth: false
},
onLoad: async function () {
var that = this;
// 查看是否授權(quán)
wx.getSetting({
success: function (res) {
if (res.authSetting['scope.userInfo']) {
wx.login({
success: loginRes => {
// 獲取到用戶的 code 之后:loginRes.code
wx.getUserInfo({
success: async function (res) {
// 這里處理業(yè)務(wù)邏輯
}
})
}
})
} else {
// 用戶沒有授權(quán)
}
}
});
},
bindGetUserInfo: function (e) {
// 需要什么信息都從e中拿到 以下部分業(yè)務(wù)邏輯
if (e.detail.userInfo) {
//用戶按了允許授權(quán)按鈕
var that = this;
// 獲取到用戶的信息
wx.login({
success: async res => {
const aUserModel = new UserModel();
const params = {
code: res.code,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
}
const { data } = await aUserModel.login({ ...params })
if(data.roles){
// do ...
}
if (data.mobile) {
// do ...
}
}
});
//授權(quán)成功后,通過改變 isHide 的值,讓實現(xiàn)頁面顯示出來,把授權(quán)頁面隱藏起來
that.setData({
isHide: false
});
} else {
//用戶按了拒絕按鈕
wx.showModal({
title: '警告',
content: '拒絕授權(quán),您將無法使用小程序',
showCancel: false
});
}
},
getPhoneNumber: async function (e) {
if (e.detail.encryptedData) {
//用戶按了允許授權(quán)按鈕
const aUserModel = new UserModel();
const params = {
userId: userInfo.id,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
}
// do ...
} else {
//用戶按了拒絕按鈕
wx.showModal({
title: '警告',
content: '拒絕授權(quán),您將無法使用小程序',
showCancel: false
})
}
},
// ...
})
復(fù)制代碼
路由
路由跳轉(zhuǎn)的各個方法可以去官網(wǎng)學(xué)習(xí),這里提遇到的坑,navigateTo路由跳轉(zhuǎn)最多只能10層,所以使用的時候需要考慮是不是確定需要歷史記錄。為什么要這么說呢。場景:一個列表頁面(如下圖),用戶的檔案是可以修改的,如果用navigateTo跳轉(zhuǎn)(/page/archivesEdit?id=1923XXXX),修改保存用navigateTo(/page/archivesList),這樣來回編輯跳轉(zhuǎn)10次就不讓點擊跳轉(zhuǎn)了。
解決:思考那我用2個redirectTo 行不行?redirectTo是關(guān)閉當前歷史記錄跳轉(zhuǎn)到下一頁面。造成了我跳轉(zhuǎn)到修改頁面點擊微信自帶的返回是直接跳過列表頁面跳轉(zhuǎn)到首頁。這個時候測試小姐姐就又要提bug單了……
完美姿勢:就是用navigateTo和navigateBack。我再編輯保存的時候返回用navigateBack返回。這樣小程序的路由棧就一會在2-3層之間。當然有時候在列表頁面會遇到要重新條用接口,這時候路由跳轉(zhuǎn)提供了幾個重要的鉤子函數(shù)onShow,onHide,我們可以在onShow的時候可以條用一下列表的接口。
這2個鉤子函數(shù)足夠我們簡單的跳轉(zhuǎn),更復(fù)雜的場景下可以通過存Storage這種存取參數(shù)來返回到上一個頁面進行操作,感覺不是優(yōu)雅,但是沒有好的辦法解決了。
Storage
場景:storage有2種方式獲取,當你直接wx.getStorageSync('xxx')獲取一個id,去請求接口的可能是獲取不到就已經(jīng)發(fā)送請求了,導(dǎo)致出現(xiàn)bug。因為wx.getStorageSync('xxx')是異步的,我們可以利用 async/await去方便的使用:
onLoad: async function (options) {
const editListParams = await wx.getStorageSync('editListParams')
this.findReportDetails(editListParams)
}
復(fù)制代碼
webView
webview不是在某個頁面使用的,當時我以為是類似iframe這種東西嵌入到頁面。正確的使用態(tài)度是新建一個page頁面,然后跳轉(zhuǎn)到這個page去使用。例如跳轉(zhuǎn)到小程序關(guān)聯(lián)的公眾號文章:
other.wxml
<navigator url="/pages/webView/webView" hover-class="none">跳轉(zhuǎn)到webView</navigator>
webView.wxml
<web-view src="https://mp.weixin.qq.com/s/xxxx"></web-view>
復(fù)制代碼
request
微信自帶的網(wǎng)絡(luò)下的request,雖然能拿來就用,如果不封裝就會造成代碼冗余。大家可自行參考如下封裝
ajax.js
import { baseURL } from '../config/interfaceURL' // baseUrl
class AJAX {
AJAX ({ url, methods = 'GET', data = {} }) {
return new Promise((resolve, reject) => {
this.request(url, resolve, reject, methods, data)
})
}
request (url, resolve, reject, methods, data) {
wx.request({
url: baseURL + url,
method: methods,
data: data,
header: {
'content-type': 'application/json'
},
success: res => {
const code = res.statusCode.toString()
if (code.startsWith('2')) {
resolve(res)
} else {
reject()
const errorMessage = res.data.message
AJAX.showError(errorMessage)
}
},
fail: err => {
reject()
AJAX.showError("網(wǎng)絡(luò)異常,請稍后重試!")
}
})
}
static showError (errorMessage) {
wx.showToast({
title: errorMessage,
icon: 'error',
duration: 2000
})
}
static serializeLink (obj) { // 序列化get請求
let temp = '?'
for (let index in obj) {
if(obj.hasOwnProperty(index)){
temp += (index + '=' + obj[index] + '&')
}
}
return temp.substr(0, temp.length - 1)
}
}
export default AJAX
// model層調(diào)用
UserModel.js
import AJAX from '../utils/AJAX'
export class UserModel extends AJAX {
// 小程序授權(quán)登陸
login (params) {
return this.AJAX({
url: `/service/api/users/applet/login`,
data: params,
methods: 'POST'
})
}
}
// control調(diào)用
index.js
async onLoad (options){
const aUserModel = new UserModel()
const params = {
code: loginRes.code,
encryptedData: res.encryptedData,
iv: res.iv
}
const { data } = await aUserModel.login({ ...params })
// 其他
}
復(fù)制代碼
npm生態(tài)以及第三方ui框架
直接通過初始化的微信小程序項目里面沒有package.json文件。所以在使用npm install xxx 是沒有卵用。所以我們要自己在文件夾根目錄下執(zhí)行npm init 。這時候才能通過微信開發(fā)者工具構(gòu)建npm,構(gòu)建成功會生成一個目錄。推薦用有贊的vant小程序版,社區(qū)較活躍,使用起來不會有很多坑。
雙向綁定
對于習(xí)慣使用vue的開發(fā)者來說,少了這個v-model語法糖。在處理表單的雙向綁定會顯得比較蛋疼。所以還是有必要說下小程序里面的雙向綁定是怎么樣的。
file:index.js
Page({
data: {
list: []
},
onLoad: function (options) {
// do ...
},
onInput (e) {
let value = e.detail.value
let temp = e.target.dataset.name.split(',')
let tempKey = temp[1]
let tempIndex = temp[0]
let tempSubIndex = temp[2]
let targetKey = `list[${tempIndex}].children[${tempSubIndex}].${tempKey}`
this.setData({
[targetKey]: value
})
}
})
file:index.wxml
<block wx:for="{{item.children}}" wx:for-item="subItem" wx:key="{{index}}">
<view class="td" style="height: {{ 100 / item.children.length}}%;">
<input placeholder-style="color:#ccccccc;" type="text" placeholder="未填寫" value="{{subItem.testResult}}" data-name="{{idx}},testResult,{{index}}" bindinput="onInput"/>
</view>
</block>
復(fù)制代碼
下載圖片和下載圖片授權(quán)
這里場景是下載一個固定的靜態(tài)資源圖片,網(wǎng)絡(luò)圖片需先配置download域名才能生效,方法如下:
savePhoto () {
const _this = this;
wx.getImageInfo({
src: '/static/images/home/Qr.png',
success: function (res) {
wx.saveImageToPhotosAlbum({
filePath: res.path,
success (result) {
_this.setData({ show: false });
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail (err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
wx.openSetting({
success (settingdata) {
if (settingdata.authSetting['scope.writePhotosAlbum']) {
_this.savePhoto()
} else {
wx.showToast({
title: '獲取權(quán)限失敗,無法保存圖片',
icon: 'success',
duration: 2000
})
}
}
})
}
}
})
}
})
}
復(fù)制代碼
保存圖片也是需要授權(quán)的,看代碼就完事了。
其他
textarea 在ios上表現(xiàn)會有padding值,這個就坑了。我采用要不全是textarea或者全是input 這種去實現(xiàn)表單的填寫,其他樣式問題也蠻多的,有點ie的味道,多用flex float去解決一些差異吧~
文章每個點都是開發(fā)小程序的時候遇到的問題,本人能力有限,歡迎大家提出自己的問題。小程序坑還是蠻多的,而且寫博客也蠻難得,碼字不易,覺得有用的話點個在看吧!
原文作者:Rolan