1. 萬惡的button
由于小程序的限制痊土,很多地方必須用到button來做嗦锐,如分享按鈕open-type="share",授權(quán)按鈕open-type="getUserInfo"等,但是小程序?qū)utton做了很多的默認(rèn)限制:
1.1 默認(rèn)的padding
button默認(rèn)設(shè)置了padding-left: 14rpx; padding-right: 14rpx
1.2 boder
button的上下border是通過button::after設(shè)置的惊畏,所以要去除button的boder需要設(shè)置
button::after {
border: 0;
}
1.3 button:hover
默認(rèn)的扰法,小程序會(huì)給button加上hover時(shí)的樣式,所以衅鹿,如果發(fā)現(xiàn)點(diǎn)擊了之后button變丑了撒踪,就要去設(shè)置button-hover樣式了,或者直接設(shè)置hover-class="none"
大渤,此時(shí)無點(diǎn)擊效果制妄,這點(diǎn)文檔上有說明。
2. 不支持媒體查詢
@media screen and (min-device-height:748px) and (max-device-height:812px) and (-webkit-min-device-pixel-ratio:3){
html, body{
height: 2208px;
}
}
H5頁面中做iphone X的適配可能會(huì)這么寫泵三,但是小程序中這樣寫不生效耕捞。
小程序中如果要針對(duì)iphone X做兼容,需要使用js烫幕,通過wx.getSystemInfo(OBJECT)
獲取系統(tǒng)信息
wx.getSystemInfo({
success: res=> {
this.globalData.device = JSON.stringify(res);
let model = res.model
// 判斷是否是iPhone X
if(model.toLowerCase().search('iphone x') != -1){
this.globalData.isIphoneX = true;
}else{
this.globalData.isIphoneX = false;
}
}
})
3. 關(guān)于背景圖片的使用
在wxss文件中俺抽,不能引用本地圖片作為背景圖片,否則较曼,即便開發(fā)者工具上預(yù)覽正常磷斧,真機(jī)上是讀不出圖片的,解決辦法是:將本地圖片轉(zhuǎn)為base64格式捷犹,或者是使用網(wǎng)絡(luò)圖片
4. 關(guān)于scroll-view組件的使用
4.1 scroll-view
橫向滑動(dòng)
當(dāng)使用scroll-view組件作scroll-x橫向滑動(dòng)時(shí)弛饭,scroll-view層需要設(shè)置white-space: nowrap;
,scroll-view中的子項(xiàng)必須使用display: inline-block;
做布局伏恐,不能使用float
浮動(dòng)布局孩哑,否則組件會(huì)失效。
另外翠桦,默認(rèn)情況下横蜒,橫向滾動(dòng)塊底部會(huì)有一個(gè)滾動(dòng)條,要隱藏滾動(dòng)條销凑,需要設(shè)置:
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
這一點(diǎn)在官方文檔中也沒有提及丛晌。
scroll-view做豎向滑動(dòng)時(shí),需要給scroll-view
一個(gè)固定的高度斗幼,盡量不要通過給scroll-view
的父盒子使用flex布局澎蛛,然后scroll-view
層使用flex:1;
來設(shè)置高度,否則在ios上可能會(huì)出現(xiàn)一些無法滑動(dòng)等不可預(yù)知的問題蜕窿。
4.2 scroll-view
豎向滾動(dòng)
scroll-view
豎向滾動(dòng)時(shí)綁定bindscroll="scrollHandler"
滾動(dòng)監(jiān)聽時(shí)谋逻,上拉加載數(shù)據(jù)除了要判斷是否已經(jīng)獲取到最后一頁數(shù)據(jù)后防止繼續(xù)發(fā)出接口請(qǐng)求呆馁,還要在每次接口請(qǐng)求發(fā)出之時(shí)判斷請(qǐng)求是否已經(jīng)回來,在請(qǐng)求未回來之前禁止繼續(xù)發(fā)送請(qǐng)求毁兆。
export default {
data() {
return {
isLoadEnd: true, // 用于判斷當(dāng)前請(qǐng)求是否已完成
isLoadAll: false // 用于判斷是否已經(jīng)加載了所有數(shù)據(jù)浙滤,所有數(shù)據(jù)加載完后不再發(fā)送請(qǐng)求
};
},
methods: {
scrollHandler() {
if (!this.isLoadEnd || this.isLoadAll) return;
this.isLoadEnd = false;
// 下面是發(fā)送請(qǐng)求
ajax.getData().then(res=> {
this.isLoadEnd = true;
// 這里根據(jù)接口返回的數(shù)據(jù)判斷是否數(shù)據(jù)已經(jīng)全部加載,全部加載設(shè)置 this.isLoadAll = true;
}).catch(err=> {
this.isLoadEnd = true;
});
}
}
};
5. canvas繪制網(wǎng)絡(luò)圖片
使用canvas繪制圖片時(shí)气堕,不能使用網(wǎng)絡(luò)圖片纺腊,因此如果要繪制網(wǎng)絡(luò)圖片,需要使用downloadFile
或getImageInfo
將圖片緩存到本地茎芭,另外還要在小程序后臺(tái)配置好downloadFile
安全域名揖膜,否則在真機(jī)上會(huì)出現(xiàn)奇怪的現(xiàn)象,打開調(diào)試模式圖片就加載正常梅桩,關(guān)閉調(diào)試模式就加載不出來壹粟。
const ctx = wx.createCanvasContext('myCanvas')
const url = '網(wǎng)絡(luò)圖片路徑'
wxGetImageInfo (url) {
return new Promise((resolve, reject) => {
// 獲取圖片信息。網(wǎng)絡(luò)圖片需先配置download域名才能生效摘投。
wx.getImageInfo({
src: url,
success: res => {
resolve(res)
},
fail: e => {
reject(e)
}
})
})
}
const {path} = wxGetImageInfo(url)
ctx.drawImage(path, 0, 0, canvasWith, canvasHeight)
ctx.draw(fakse, () => {
wxApi.wxCanvasToTempFilePath({
width: 750 * dpr,
height: 1138 * dpr,
canvasId: 'myCanvas'
}).then(res => {
this.tempImg = res.tempFilePath
wxApi.hideLoading()
}).catch(() => {
wxApi.hideLoading()
})
})
- 圖片繪制成功要進(jìn)行預(yù)覽煮寡,則要調(diào)用 wx.canvasToTempFilePath() 將畫布內(nèi)容導(dǎo)出生成圖片;
- 圖片導(dǎo)出成功后得到的 tempFilePath 需要放在 image 組件src中犀呼,不能用做 background-image 的 url 幸撕,否則真機(jī)下會(huì)顯示不出圖片;
- 將得到的 tempFilePath 傳入 wx.saveImageToPhotosAlbum() 保存到相冊(cè)外臂;
- 保存到相冊(cè)需要用戶授權(quán)坐儿,因此要考慮用戶拒絕授權(quán)的情況,拒絕之后需要將保存圖片的按鈕變?yōu)?<button open-type="openSetting"></button>打開設(shè)置頁面宋光;
- 因?yàn)橐紤]到新老用戶是否授權(quán)的情況貌矿,需要兩個(gè)不同的button,另外還要利用到wx.getSetting()來獲取授權(quán)信息罪佳,這里會(huì)相比比較麻煩逛漫;
6. 彈窗遮罩層滾動(dòng)穿透問題
彈窗最外層元素上綁定禁止?jié)L動(dòng)事件 catchtouchmove="touchmoveHandler"
<view catchtouchmove="touchmoveHandler>
<scroll-view scroll-y>這里寫彈窗的具體內(nèi)容</scroll-view>
</view>
// js部分
touchmoveHandler () {
return false;
}
- 針對(duì) catchtouchmove 方法,原生小程序使用 catchtouchmove="touchmoveHandler"赘艳,mpvue 中使用 @touchmove.stop="touchmoveHandler"酌毡,注意 touchmoveHandler 要給個(gè)空方法,否則會(huì)報(bào)警
- 綁定 catchtouchmove="touchmoveHandler" 后蕾管,彈窗內(nèi)部如果也有滾動(dòng)區(qū)域的話枷踏,則彈窗內(nèi)部的滾動(dòng)也會(huì)失效,即 catchtouchmove 禁止了所有區(qū)域的滾動(dòng)行為掰曾;
- 針對(duì)第2點(diǎn)旭蠕,如果彈窗內(nèi)還有滾動(dòng)條,則不能使用catchtouchmove方法,按照H5的做法掏熬,給 頁面 最外層添加
height:100%;overflow:hidden;
佑稠,但是會(huì)出現(xiàn)彈窗出來時(shí)頁面會(huì)有一個(gè)返回頂部的toTop現(xiàn)象,交互很不友好孽江,并且在ios(某些機(jī)型)上會(huì)有bug:先在滾動(dòng)區(qū)域滾動(dòng)幾下讶坯,然后再在外層滾動(dòng)幾下番电,此時(shí)再回到滾動(dòng)區(qū)域滑動(dòng)會(huì)滑動(dòng)不了岗屏; - 針對(duì)第3點(diǎn)bug,如果一定要解決滾動(dòng)穿透漱办,按照1的方法这刷,只是在彈窗區(qū)域內(nèi)需要滾動(dòng)的地方使用
scroll-view
進(jìn)行包裹。
.noScroll {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 0;
overflow: hidden;
}
并且需要?jiǎng)討B(tài)獲取頁面當(dāng)前滾動(dòng)的距離娩井,然后動(dòng)態(tài)修改containerView的top值暇屋,這樣做相對(duì)麻煩,因此建議此類情況允許穿透洞辣;
7. 兼容問題
7.1 onPullDownRefresh
下拉刷新兼容問題
使用onPullDownRefresh
下拉刷新時(shí)咐刨,如果將wx.stopPullDownRefresh()
放在接口請(qǐng)求的回調(diào)中執(zhí)行并且在請(qǐng)求過程中使用了小程序自帶的showToast
或showLoading
等交互反饋時(shí),在ios上會(huì)出現(xiàn)下拉之后反彈過大頁面不會(huì)回彈至頂部的問題扬霜,android上正常定鸟。目前解決方法是:
onPullDownRefresh: function () {
this.getInfo() // 發(fā)送請(qǐng)求
wx.stopPullDownRefresh() // 關(guān)閉下拉刷新
}
// 或者是加個(gè)定時(shí)器
onPullDownRefresh: function () {
this.getInfo() // 發(fā)送請(qǐng)求
setTimeout(()=> {
wx.stopPullDownRefresh() // 關(guān)閉下拉刷新
}, 800)
}
參考: https://blog.csdn.net/weichen913/article/details/79360658
7.2 font-weight
設(shè)置字體加粗的兼容問題
小程序中設(shè)置font-weight
數(shù)字時(shí),在android
機(jī)上無效著瓶。只有700
和bold
有效联予。
7.3 scroll-view
設(shè)置height:100%
引起的滑動(dòng)卡頓問題
部分android機(jī)上,在scroll-view
上設(shè)置height:100%
會(huì)導(dǎo)致頁面上滑時(shí)不流暢的卡頓問題材原,不設(shè)置自動(dòng)撐開即可沸久。
8. 搖一搖 - 加速度計(jì)
由于小程序目前沒有提供搖一搖的API,因此要實(shí)現(xiàn)搖一搖的功能需要借助加速度計(jì)來實(shí)現(xiàn)余蟹,與加速度計(jì)相關(guān)的API有3個(gè):監(jiān)聽加速度數(shù)據(jù)wx.onAccelerometerChange(CALLBACK)
卷胯、開始監(jiān)聽加速度數(shù)據(jù)wx.startAccelerometer(OBJECT)
和停止監(jiān)聽加速度數(shù)據(jù)wx.stopAccelerometer(OBJECT)
。
然后威酒,坑來了窑睁。。兼搏。
wx.stopAccelerometer(OBJECT)
停止監(jiān)聽卵慰,這個(gè)方法是停止了監(jiān)聽,再晃動(dòng)手機(jī)不會(huì)走回調(diào)方法了佛呻,但是它并不移除監(jiān)聽裳朋。
那么問題來了,在某個(gè)頁面每調(diào)用一次第一個(gè)api它就會(huì)注冊(cè)一個(gè)監(jiān)聽,第三個(gè)api并不能移除掉監(jiān)聽鲤嫡,導(dǎo)致你再次開啟的時(shí)候就會(huì)有多個(gè)回調(diào)方法在同時(shí)進(jìn)行送挑。就好像是只提供了addEventListener
,但卻沒有提供removeEventListener
暖眼。
如果小程序中有多個(gè)頁面需要監(jiān)聽加速度惕耕,如A、B兩個(gè)頁面诫肠,A頁面司澎,onReady
事件后wx.onAccelerometerChange
,離開A頁面栋豫,stopAccelerometer
停止監(jiān)聽挤安。到了B頁面,A頁面的事件還存在丧鸯。在B頁面搖一搖蛤铜,就會(huì)觸發(fā)兩個(gè)頁面的回調(diào)。
解決方法:
在微信小程序啟動(dòng)的時(shí)候就調(diào)用監(jiān)聽方法丛肢,在回到方法中通過getCurrentPages()
獲取到當(dāng)前的頁面围肥,在當(dāng)前頁面調(diào)用你想回調(diào)的方法。
onLaunch: function () {
wx.onAccelerometerChange((e) => {
var pages = getCurrentPages()
var currentPage = pages[pages.length - 1]
if (currentPage.onAccelerometerChange) {
currentPage.onAccelerometerChange(e)
}
})
}
9. video組件
- 在小程序中蜂怎,
video
組件的層級(jí)跟canvas組件一樣穆刻,層級(jí)是最高的,設(shè)置z-index
無效派敷; - 使用 API
wx.createVideoContext(videoId)
的seek()
方法時(shí)蛹批,要求視頻資源必須是網(wǎng)絡(luò)資源,不能是本地的視頻資源篮愉,否則seek()
設(shè)置無效腐芍; - 如果
video
內(nèi)部設(shè)置了autoplay="{{true}}"
自動(dòng)播放,在 ios 下试躏,即便設(shè)置過this.videoContext.pause()
猪勇,視頻一加載也會(huì)觸發(fā)組件的bindplay
事件,而 android 下不會(huì)颠蕴;
10. mpvue
中關(guān)于data的值不會(huì)重置的問題
mpvue
中泣刹,放在data中的數(shù)據(jù),在頁面沒有銷毀(點(diǎn)擊左上角或手機(jī)返回鍵返回上一層犀被,再進(jìn)入頁面)的情況下椅您,data的數(shù)據(jù)不會(huì)進(jìn)行重置,因此在小程序onUnload的時(shí)候要將數(shù)據(jù)進(jìn)行一次重置寡键,也可以在onLoad或onShow生命周期數(shù)據(jù)操作之前使用Object.assign(this.$data, this.$options.data());
將所有的數(shù)據(jù)重置為初始值掀泳;
11. ad
組件 - Banner廣告
小程序的banner廣告會(huì)存在加載失敗的情況,應(yīng)該在監(jiān)聽到加載成功的時(shí)候再將廣告顯示出來,否則即便失敗的情況员舵,廣告也會(huì)在頁面中占位脑沿,顯示的 暫無廣告 的樣式。并且需要將isLoadAd放在父容器上马僻,不能直接在ad
組件上使用v-if
做判斷庄拇,否則不生效。
<view :class="{hide: !isLoadAd}">
<ad unit-id="adunit-****" @load="adLoadSuccess" @error="adLoadFail"></ad>
</view>
data() {
return {
isLoadAd: true
};
}
// 廣告加載成功監(jiān)聽
adLoadSuccess() {
this.isLoadAd = true;
},
// 廣告加載失敗監(jiān)聽
adLoadFail() {
this.isLoadAd = false;
}
12. 激勵(lì)視頻
wx.createRewardedVideoAd(Object object)
創(chuàng)建一個(gè)激勵(lì)式視頻廣告韭邓,返回一個(gè)單例對(duì)象措近,該對(duì)象僅對(duì)單個(gè)頁面有效,不允許跨頁面使用仍秤。多次創(chuàng)建熄诡,將返回同一個(gè)激勵(lì)式視頻廣告對(duì)象(RewardedVideoAd)。該方法在基礎(chǔ)庫 2.6.0 開始支持诗力,開發(fā)者需做兼容處理。
注意:
激勵(lì)視頻會(huì)存在加載失敗的情況我抠,因此所有觀看視頻相關(guān)的操作必須是在視頻加載成功后(isLoadedVideoAd=true
)才執(zhí)行苇本。
export default {
data() {
this.videoAd = null;
return {
isLoadedVideoAd: false // 激勵(lì)視頻是否加載成功,默認(rèn)不展示
};
},
onLoad() {
this.createVideoAd(); // 創(chuàng)建激勵(lì)視頻
},
onUnload() {
this.destoryVideoAd(); // 銷毀激勵(lì)視頻及相關(guān)視頻監(jiān)聽事件
},
methods: {
// 創(chuàng)建激勵(lì)視頻
createVideoAd() {
if (wx.createRewardedVideoAd && !this.videoAd) {
this.videoAd = wx.createRewardedVideoAd({
adUnitId: '你的視頻廣告id'
});
this.videoAdLoadHandler();
this.videoAdErrorHandler();
this.videoAdCloseHandler();
},
// 監(jiān)聽激勵(lì)視頻是否加載成功
videoAdLoadHandler() {
this.videoAd.onLoad(()=> {
this.isLoadedVideoAd = true;
});
},
// 監(jiān)聽視頻加載出錯(cuò)
videoAdErrorHandler() {
this.videoAd.onError(()=> {
// 視頻加載出錯(cuò)菜拓,請(qǐng)稍后重試
this.deleteVideoAd();
});
},
// 監(jiān)聽視頻的播放完成事件
videoAdCloseHandler() {
this.videoAd.onClose(status=> {
// 2.1.0以前的版本兼容瓣窄,status是一個(gè)undefined
if ((status && status.isEnded) || status === undefined) {
// 正常播放結(jié)束-觀看完成的邏輯寫在這里
} else {
// 播放中途退出-相應(yīng)的處理邏輯寫在這里
}
});
},
// 銷毀激勵(lì)視頻廣告組件
destoryVideoAd() {
if (this.videoAd) {
this.videoAd.offLoad();
this.videoAd.offClose();
this.videoAd.offError();
this.videoAd = null;
this.isLoadedVideoAd = false;
}
},
// 顯示激勵(lì)視頻廣告
videoAdShow() {
if (this.videoAd && this.videoAd.show && typeof this.videoAd.show === 'function') {
this.videoAd.show().catch(()=> {
// 失敗后重試
this.videoAd.load().then(()=> {
this.videoAd.show(); // 加載成功重新顯示視頻廣告
}).catch(()=> {
// 視頻加載失敗,請(qǐng)稍后重試
this.deleteVideoAd();
});
});
}
}
}
}
};
參考:https://wximg.qq.com/wxp/pdftool/get.html?post_id=851
13. webView - 小程序跳H5
web-view
組件: 承載網(wǎng)頁的容器纳鼎。會(huì)自動(dòng)鋪滿整個(gè)小程序頁面俺夕。
由于web-view
組件會(huì)自動(dòng)鋪滿整個(gè)小程序頁面,因此每個(gè)小程序要跳H5的鏈接贱鄙,都需要一個(gè)中間頁來承載劝贸。
而如果一個(gè)小程序中如果有多個(gè)要跳H5的鏈接,是不是就需要?jiǎng)?chuàng)建多個(gè)承載頁逗宁?
當(dāng)然不需要映九,否則就太麻煩了。因此瞎颗,建立一個(gè)承載頁件甥,然后將web-view
的src傳入即可。
<template>
<div class="webv-container">
<web-view :src="webSrc"></web-view>
</div>
</template>
<script>
export default {
data() {
return {
webSrc: ''
};
},
onLoad() {
const rootQuery = this.$root.$mp.query || {};
this.webSrc = decodeURIComponent(rootQuery.src);
}
};
</script>
tip:
- 父級(jí)頁面?zhèn)魅雜rc時(shí)一定要進(jìn)行encodeURIComponent哼拔,然后在webView頁面中進(jìn)行decodeURIComponent引有;
參考:
http://www.iamaddy.net/2017/07/wxapp-accelerometer/
https://blog.csdn.net/frankkay/article/details/80485095