title
總結(jié)
微信小程序開發(fā)
中遇到的坑,一些坑你得一個(gè)一個(gè)的跳啊,/(ㄒoㄒ)/~~aboutme
github
blog
1,頁面跳轉(zhuǎn)和參數(shù)傳遞實(shí)例
首先說一下我遇到的需求
有一個(gè)我的消息頁面,里面的數(shù)據(jù)都是后端返回的,返回的數(shù)據(jù)大致如下,有一個(gè)是數(shù)據(jù)url是要控制跳轉(zhuǎn)到哪個(gè)頁面,可能是tab頁面也可能是非tab頁面,但是微信小程序中跳轉(zhuǎn)到tab和非tab頁面用的api不是同一個(gè),但是在頁面中渲染肯定是要用到循環(huán)的,難道要再多個(gè)參數(shù)來判斷是跳轉(zhuǎn)到tab頁面還是非tab頁面?
[
{
"id": 2121,
"title": "test",
"body": "test",
"url": "url",
"pic": "pic",
"created_at": "2017-07-01 12:34:56"
}, {
"id": 2122,
"title": "test",
"body": "test",
"url": "url",
"pic": "pic",
"created_at": "2017-07-01 12:34:56"
},
]
- 后一般的小程序中我用的框架是wepy,底部的tab組件就是我自己寫的,沒有用到小程序自己提供的那一個(gè),因?yàn)槲覀冞€要實(shí)現(xiàn)一個(gè)需求,有消息時(shí),
底部tab會(huì)出現(xiàn)小紅點(diǎn)
,還有以下彈窗要把底部tab覆蓋掉,這些需求如果用小程序提供的那一個(gè)tab組件的話根本實(shí)現(xiàn)不了;而且不用wepy框架的話,自己做一個(gè)tab實(shí)現(xiàn)的過程很惡心,小程序雖然實(shí)現(xiàn)了組件化,但是它實(shí)現(xiàn)的組件化并不像vue和react那樣實(shí)現(xiàn)的是真正的組件化,你需要哪個(gè)組件就直接import進(jìn)來,小程序的組件化實(shí)現(xiàn)可查看官方文檔,js,css和html都是要分別引入的 - 自己實(shí)現(xiàn)的tab頁面整體是一個(gè)非tab頁面,所有整個(gè)小程序中就不存在絕對的tab頁面,所以用
navigator
這個(gè)組件,想要跳轉(zhuǎn)到tab頁面可以通過在url上拼接參數(shù)
<view class="mesList" wx:for="{{unReadList}}" wx:key="unique">
<navigator url="/pages/index?tab=0" hover-class="none" >
<text>{{item.body}}</text>
<view class="messageTime">{{item.created_at}}</view>
</navigator>
</view>
然后再index頁面的onload中判斷顯示哪個(gè)tab
onLoad(options) {
if (options && options.tab) {
this.tab = parseInt(options.tab);
this.$apply();
}
}
2,微信小程序授權(quán)處理
- 微信小程序提示授權(quán)彈窗,如果用戶第一次點(diǎn)擊拒絕之后,一段時(shí)間將不會(huì)再次彈出來,然后用戶又不知道什么原因用不了小程序,這是個(gè)很糟糕的用戶體驗(yàn),我們應(yīng)該優(yōu)雅的處理這種情況
- 采用的解決方法參考
3, 登錄問題的處理
- 兩個(gè)登錄接口,一個(gè)get,判斷是否已經(jīng)還需要登錄,如果返回true,則需要登錄,如果返回false,則不需要登錄
- 如果返回true,則需要去請求更一個(gè)post的登錄接口,這時(shí),你需要獲取第一個(gè)get請求的返回信息中的
session
,之后每次請求求都需要帶上他 - 在返回true的時(shí)候還需要做一件事兒,就是把返回信息中的
session
存儲到storage
,即調(diào)用setStorage
,然后在之后每次請求數(shù)據(jù)的時(shí)候在headers
里加上這個(gè)字段
function getStorage(key) {
return new Promise(function (resolve, reject) {
// 先判斷本地?cái)?shù)據(jù)存儲有沒有cookie
wx.getStorage({
key: key,
success: function (res) {
resolve(res.data);
},
fail: function (res) {
resolve(null);
},
});
});
}
function setStorage(key, value) {
return new Promise(function (resolve, reject) {
wx.setStorage({
key: key,
data: value,
success: function (res) {
// TODO: 不知道返回什么
resolve(res.data);
},
fail: function (res) {
reject(res.errMsg);
},
});
});
}
4,wx.getStorage安卓手機(jī)上返回的錯(cuò)誤信息是getStorage:fail
,ios返回getStorage:fail data not found
- 在判斷一些api返回的錯(cuò)誤信息時(shí),最好不要通過判斷具體的錯(cuò)誤信息來處理錯(cuò)誤
function getStorage(key) {
return new Promise(function (resolve, reject) {
// 先判斷本地?cái)?shù)據(jù)存儲有沒有cookie
wx.getStorage({
key: key,
success: function (res) {
resolve(res.data);
},
fail: function (res) {
resolve(null);
// 下面注釋的部分即為剛開始犯的錯(cuò)誤,導(dǎo)致有可能ios或安卓或部分機(jī)型顯示不出數(shù)據(jù)
// if (res.errMsg == 'getStorage:fail' || res.errMsg == 'getStorage:fail data not found') {
// console.log('沒有cookie');
// resolve(null);
// } else {
// console.log('這是一個(gè)問題');
// reject(res.errMsg);
// }
},
});
});
}
5,小程序解決異步
- 如果項(xiàng)目中沒有用到babal,小程序本身的支持只支持到es6的語法,所以解決異步的問題就不能使用es7的
async
和await
,只能使用promise
來解決異步,但是每個(gè)api
上都進(jìn)行一次封裝(如下),這種做法太惡心了
function login() {
return new Promise(function (resolve, reject) {
wx.login({
success: function (res) {
resolve(res);
},
fail: function (res) {
reject(res.errMsg);
},
});
});
}
- 基于微信的API的
prototype
上進(jìn)行了`promise``的封裝
function promiseify(func) {
return (args = {}) => {
return new Promise((resolve, reject) => {
func.call(wx, Object.assign(args, {
success: resolve,
fail: reject,
}));
})
}
}
for (const key in wx) {
if (Object.prototype.hasOwnProperty.call(wx, key) && typeof wx[key] === 'function') {
wx[`_${key}`] = promiseify(wx[key]);
}
}
6,怎么保證在調(diào)用其他接口之前已經(jīng)調(diào)用過登錄的接口了
- 我采用執(zhí)行隊(duì)列的方式來解決,問題可以簡化為有兩個(gè)按鈕,點(diǎn)擊第一個(gè)按鈕輸出這是第幾次輸出
d1
,但是必須在點(diǎn)擊完d2
之后,isPrint
變?yōu)?code>true時(shí),才允許輸出,在isPrint
為false
的時(shí)候點(diǎn)擊d1
,需要把要輸出的內(nèi)容暫時(shí)存儲起來,等isPrint
變?yōu)?code>true時(shí),暫存起來的輸出現(xiàn)在才可以輸出出來
// html
<div class="first">按鈕一</div>
<div class="second">按鈕二</div>
// js
const d1 = document.querySelector('.first');
const d2 = document.querySelector('.second');
let count = 0; // 用來記錄第幾次輸出
let isPrint = false; // 是否允許輸出
let arr = []; // 聲明一個(gè)數(shù)組,用來存儲
function clickCount() {
count++;
console.log('這是第' + count + '次輸出d1');
}
d1.onclick = function () {
console.log(isPrint);
console.log(arr);
if (isPrint) {
if (arr.length === 0) {
clickCount();
} else {
for (let i = 0, len = arr.length; i < len; i++) {
arr[i]();
}
}
} else {
arr.push(clickCount);
console.log('不允許輸出');
}
};
d2.onclick = function () {
isPrint = true;
console.log(isPrint);
}
6,小程序問題
- 不支持跳轉(zhuǎn)外部鏈接
-
text
可以解析/n
, - 目前不支持識別圖中二維碼瑞侮,
- 背景圖片不能用本地圖片蚊俺,
-
wx.navigateTo
需要跳轉(zhuǎn)的應(yīng)用內(nèi)非 tabBar 的頁面的路徑 -
wx.switchTab
跳轉(zhuǎn)到tabBar頁面, -
wx.showToast()
,icon
只支持success
和loading
,但是支持image
,且image
優(yōu)先級高于icon
-
tabBar
頁面AnavigatorTo
到頁面B,然后BswitchTab
到A麦射,這里A會(huì)執(zhí)行onShow()
;
但是我再從A跳到B再switchTab
回來灯谣,A就不會(huì)再執(zhí)行onShow()
了潜秋,
7,總結(jié)
- 有時(shí)候在開發(fā)者工具上測試時(shí)是沒有問題的,但是真機(jī)測試卻有問題,所有開發(fā)過程中一定要在多個(gè)不同型號的手機(jī)上測試;很多時(shí)候IOS和安卓api返回的信息不同
- 在手機(jī)上打開調(diào)試的時(shí)候是好的,但是關(guān)閉調(diào)試后就會(huì)出現(xiàn)各種bug,遇到這種情況一定要一步步的去排查原因
8,后采用wepy重構(gòu)小程序遇到的一些坑
wepy文檔
1,Q: 怎么在page組件和component
組件中回去到getApp()
,就是app里面定義的函數(shù),通過this.$parent
只能拿到數(shù)據(jù)胎许,拿不到方法?
A:可以在this.$parent
的_proto
上拿到方法,即this.$parent.onLogin
2, Q:怎么實(shí)現(xiàn)按需加載
A:在compoent
組件中自定義生命周期函數(shù),并手動(dòng)觸發(fā)