抖音小程序與微信小程序差異
- 獲取用戶(hù)信息的方式
- 通過(guò)button按鈕,設(shè)置屬性 open-type="getUserInfo",獲取獲得用戶(hù)信息的授權(quán)
- 兼容性,通過(guò)wx.canIUse('button.open-type.getUserInfo')的值,來(lái)判斷按鈕是否可用
- 通過(guò)擁有上述屬性的按鈕事件bindgetuserinfo -
https://developers.weixin.qq.com/miniprogram/dev/component/button.html來(lái)獲取,事件處理函數(shù)中ev.detail.userInfo對(duì)應(yīng)的用戶(hù)信息 - wx.getUserInfo在用戶(hù)未授權(quán)的情況下,將不再出現(xiàn)授權(quán)彈窗,所以才使用引導(dǎo)用戶(hù)點(diǎn)擊按鈕的授權(quán)方式
- 通過(guò)onload生命周期,wx.getSetting來(lái)獲取用戶(hù)權(quán)限,并對(duì)用戶(hù)信息狀態(tài)賦值
<view wx:if="{{showLoginBtn}}">
<button
class="skillbtn"
bindgetuserinfo="loginFn"
open-type="getUserInfo"
>手動(dòng)授權(quán)登錄</button>
</view>
<view wx:else>
<text>請(qǐng)升級(jí)微信版本</text>
</view>
...
//查看授權(quán)按鈕是否可以使用
if(wx.canIUse('button.open-type.getUserInfo')){
_that.setData({
'showLoginBtn': true
});
};
...
//獲取用戶(hù)信息與請(qǐng)求服務(wù)器獲取userid
loginFn(ev){
var _that = this;
//獲取用戶(hù)的當(dāng)前授權(quán)設(shè)置
wx.getSetting({
success(res){
//查看【獲取用戶(hù)信息】授權(quán)
if(res.authSetting['scope.userInfo']){
wx.getUserInfo({
success(res){
var _userInfo = res.userInfo;
//獲得code,再進(jìn)行注冊(cè)
_that.registerFn(function(_code){
//請(qǐng)求后臺(tái)接口,獲取userid
});
},
fail(err){
console.log(err);
}
});
}else{
app.showPopFn({
'title':'授權(quán)失敗',
'icon': 'none',
'duration': 1000
});
}
}
})
}
1-2. 如果wx:if掛載的標(biāo)簽上條件,與通過(guò)此條件來(lái)增加標(biāo)簽上的class類(lèi)名時(shí)候,不會(huì)產(chǎn)生動(dòng)畫(huà)效果
解決: 需要增加額外條件,來(lái)改變class類(lèi)名,可能的話(huà),還要增加延時(shí)定時(shí)器來(lái)進(jìn)行這個(gè)類(lèi)名條件的設(shè)置
- 最新官方關(guān)于 用戶(hù)信息相關(guān)接口調(diào)整 -
https://developers.weixin.qq.com/community/develop/doc/000cacfa20ce88df04cb468bc52801
【背景】:
很多開(kāi)發(fā)者在打開(kāi)小程序時(shí)就通過(guò)組件方式喚起getUserInfo彈窗,如果用戶(hù)點(diǎn)擊拒絕,無(wú)法使用小程序,這種做法打斷了用戶(hù)正常使用小程序的流程,同時(shí)也不利于小程序獲取新用戶(hù)。
【注意】:
- 建議多用
getUserProfile,即便被拒絕,再次調(diào)用getUserProfile,仍可以拉起授權(quán)。 - 授權(quán)被拒后,通過(guò)wx.openSetting打開(kāi)設(shè)置菜單,是無(wú)法找到被拒的授權(quán)信息的。
官方變化:

- 新的授權(quán)書(shū)寫(xiě)方式
由于getUserProfile接口從2.10.4版本基礎(chǔ)庫(kù)開(kāi)始支持(覆蓋微信7.0.9以上版本),考慮到開(kāi)發(fā)者在低版本中有獲取用戶(hù)頭像昵稱(chēng)的訴求,對(duì)于未支持getUserProfile的情況下,開(kāi)發(fā)者可繼續(xù)使用getUserInfo能力
//--wxml
<view class="container">
<view class="userinfo">
<block wx:if="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 獲取頭像昵稱(chēng) </button>
<button wx:else open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 獲取頭像昵稱(chēng) </button>
</block>
<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>
//--js
Page({
data: {
userInfo: {},
hasUserInfo: false,
canIUseGetUserProfile: false,
},
onLoad() {
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
// 推薦使用wx.getUserProfile獲取用戶(hù)信息,開(kāi)發(fā)者每次通過(guò)該接口獲取用戶(hù)個(gè)人信息均需用戶(hù)確認(rèn)
// 開(kāi)發(fā)者妥善保管用戶(hù)快速填寫(xiě)的頭像昵稱(chēng),避免重復(fù)彈窗
wx.getUserProfile({
desc: '用于完善會(huì)員資料', // 聲明獲取用戶(hù)個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫(xiě)
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getUserInfo(e) {
// 不推薦使用getUserInfo獲取用戶(hù)信息,預(yù)計(jì)自2021年4月13日起,getUserInfo將不再?gòu)棾鰪棿?,并直接返回匿名的用?hù)個(gè)人信息
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
})
2-2. 區(qū)別與獲取用戶(hù)昵稱(chēng)與信息的授權(quán),有些授權(quán)拒絕后,再次調(diào)用API,不會(huì)再次彈出授權(quán)界面
如果用戶(hù)已拒絕授權(quán),則不會(huì)出現(xiàn)彈窗,而是直接進(jìn)入接口 fail 回調(diào)。需要發(fā)者兼容用戶(hù)拒絕授權(quán)的場(chǎng)景
以獲取用戶(hù)地理信息的授權(quán)為例

2-3. 關(guān)于授權(quán)的過(guò)期時(shí)間
- 在開(kāi)發(fā)者工具中,點(diǎn)擊 [ 清緩存-全部清楚 ] ,即可一次性清楚所有數(shù)據(jù)緩存與授權(quán)記錄信息
- 借用微信文檔說(shuō)明:在真機(jī)上,一旦用戶(hù)明確同意或拒絕過(guò)授權(quán),其授權(quán)關(guān)系會(huì)記錄在后臺(tái),直到用戶(hù)主動(dòng)刪除小程序。
直接在微信-小程序內(nèi),找到對(duì)應(yīng)的小程序?qū)⑵鋭h除,可能的話(huà),再加上(我-設(shè)置-通用-存儲(chǔ)空間-緩存-清理),更加干凈的清理對(duì)應(yīng)小程序的各種數(shù)據(jù)緩存與授權(quán)信息
rpx(responsive pixel): 可以根據(jù)屏幕寬度進(jìn)行自適應(yīng)。
規(guī)定屏幕寬為750rpx。
如在 iPhone6 上,屏幕寬度為375px,共有750個(gè)物理像素,則750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。獲取用戶(hù)坐標(biāo)
在app.json中,添加獲取目標(biāo)位置的權(quán)限:
"permission": {
"scope.userLocation": {
"desc": "你的位置信息將用于小程序位置接口的效果展示"
}
}
獲取用戶(hù)坐標(biāo) wx.getLocation
getUserLocalFn(){
var that = this;
//獲取用戶(hù)坐標(biāo)
wx.getLocation({
type: 'wgs84',
success(res){
var _userLocal = that.data.userLocal;
_userLocal.latitude = res.latitude;
_userLocal.longitude = res.longitude;
that.setData({
"userLocal": _userLocal
});
},
fail(err){
console.log(err);
}
});
}
- 圖片預(yù)加載
app.js
//圖片預(yù)加載
loadImg(_link,sucFn,errFn,cmpFn){
wx.getImageInfo({
src: _link,
success(res){
sucFn && sucFn(res);
},
fail(err){
errFn && errFn(err);
},
complete(res){
cmpFn && cmpFn(res);
}
});
},
//加載所有圖片
loadAllImgs(imgListArr,compFn){
//圖片預(yù)加載 相關(guān)
var _that = this;
var num = 0;
for(var i=0; i<imgListArr.length; i++){
;(function(i){
var _tempImg = imgListArr[i];
//加載圖片
_that.loadImg(_tempImg,function(res){
num+=1;
if(num==imgListArr.length){
compFn && compFn();
}
},function(err){
num+=1;
if(num==imgListArr.length){
compFn && compFn();
}
},null);
})(i);
}
}
使用,pages下某個(gè)頁(yè)面:
//加載所有圖片
app.loadAllImgs([
'https://www.xxx.net/minisoft/zhenze/everyDayPic_1.jpg',
'https://www.xxx.net/minisoft/zhenze/everyDayPic_2.jpg',
'https://www.xxx.net/minisoft/zhenze/everyDayPic_3.jpg'
],function(){
_that.setData({
allimgLoaded: true
});
});
通過(guò)allimgLoaded這個(gè)數(shù)據(jù)變量來(lái)切換loading條和圖片
wxml結(jié)構(gòu):
<!-- 背景圖 -->
<view class="imgBox">
<!--loadingGear 加載條 -->
<view class="loadingGear {{allimgLoaded? '':'loadingGearAc'}}">
<view class="inset">
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
<view class="blocks"></view>
</view>
</view>
<image wx:if="{{allimgLoaded}}" src="{{itemEle.picSrc}}" mode="aspectFill" />
</view>
css3 loading圖標(biāo),激活狀態(tài)運(yùn)動(dòng),否則不運(yùn)動(dòng)
wxss
/*loadingGear - 加載條2*/
.loadingGear { position:absolute; left:50%; top:50%; width:4rpx; height:4rpx; margin:-2rpx 0 0 -2rpx;
z-index:-1;
}
.loadingGear .inset { position:relative; z-index:2; width:100%; height:100%; visibility:hidden; }
/*激活*/
.loadingGearAc { z-index:9999;}
.loadingGearAc .inset { visibility:visible;
-webkit-animation:gearAni linear 2s infinite;
-moz-animation:gearAni linear 2s infinite;
-ms-animation:gearAni linear 2s infinite;
-o-animation:gearAni linear 2s infinite;
animation:gearAni linear 2s infinite;
}
.loadingGear .inset .blocks { position:absolute; left:0; bottom:0; z-index:2; width:100%; height:300%; overflow:hidden; background:#006d78; font-size:0; line-height:0;
-webkit-transform-origin:center bottom; -moz-transform-origin:center bottom; transform-origin:center bottom;
}
.loadingGear .inset .blocks:nth-child(1){ -webkit-transform:rotate(0deg) translateY(-10rpx); -moz-transform:rotate(0deg) translateY(-10rpx); transform:rotate(0deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(2){ -webkit-transform:rotate(45deg) translateY(-10rpx); -moz-transform:rotate(45deg) translateY(-10rpx); transform:rotate(45deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(3){ -webkit-transform:rotate(90deg) translateY(-10rpx); -moz-transform:rotate(90deg) translateY(-10rpx); transform:rotate(90deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(4){ -webkit-transform:rotate(135deg) translateY(-10rpx); -moz-transform:rotate(135deg) translateY(-10rpx); transform:rotate(135deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(5){ -webkit-transform:rotate(180deg) translateY(-10rpx); -moz-transform:rotate(180deg) translateY(-10rpx); transform:rotate(180deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(6){ -webkit-transform:rotate(225deg) translateY(-10rpx); -moz-transform:rotate(225deg) translateY(-10rpx); transform:rotate(225deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(7){ -webkit-transform:rotate(270deg) translateY(-10rpx); -moz-transform:rotate(270deg) translateY(-10rpx); transform:rotate(270deg) translateY(-10rpx); }
.loadingGear .inset .blocks:nth-child(8){ -webkit-transform:rotate(315deg) translateY(-10rpx); -moz-transform:rotate(315deg) translateY(-10rpx); transform:rotate(315deg) translateY(-10rpx); }
/*gearAni*/
@-webkit-keyframes gearAni {
0% { -webkit-transform:rotate(0deg); -moz-transform:rotate(0deg); transform:rotate(0deg);}
100% { -webkit-transform:rotate(360deg); -moz-transform:rotate(360deg); transform:rotate(360deg);}
}
@keyframes gearAni {
0% { -webkit-transform:rotate(0deg); -moz-transform:rotate(0deg); transform:rotate(0deg);}
100% { -webkit-transform:rotate(360deg); -moz-transform:rotate(360deg); transform:rotate(360deg);}
}
- 使用微信小程序API時(shí)候,需要先要測(cè)試下兼容
compareVersion(v1, v2){
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while(v1.length < len){
v1.push('0')
}
while(v2.length < len){
v2.push('0')
}
for(let i = 0; i < len; i++){
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2){
return true;
}else if(num1 < num2){
return false;
}
}
}
放在app.js內(nèi),pages使用js調(diào)用
如:音頻API的兼容
var _btn = app.compareVersion(version,'1.6.0');
if(_btn){
//基礎(chǔ)庫(kù) 1.6.0 開(kāi)始支持,低版本需做兼容處理。
InnerAudioContext = wx.createInnerAudioContext();
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用音頻功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
- 跳轉(zhuǎn)到第三方小程序,需要獲知對(duì)方的小程序APPID
也可以放在app.js內(nèi)方便,統(tǒng)一調(diào)用
jumpOtherMinisoft(_appid,_path,sucFn,errFn){
var _that = this;
//兼容
var version = wx.getSystemInfoSync().SDKVersion;
var _btn = _that.compareVersion(version,'1.3.0');
if(_btn){
//基礎(chǔ)庫(kù) 1.3.0 開(kāi)始支持
wx.navigateToMiniProgram({
appId: _appid,
path: _path,
success(res){
sucFn && sucFn(res);
},
fail(err){
errFn && errFn(err);
}
});
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用該功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
}
pages頁(yè)面內(nèi)js直接使用
app.jumpOtherMinisoft('wx2c348cf579062e56','page/index/index?id=123',null,function(err){
console.log(err);
app.showPopFn({
'title':'跳轉(zhuǎn)小程序失敗'
});
});
7-2. 通過(guò)標(biāo)簽navigater跳轉(zhuǎn)
<navigator
target="miniProgram"
open-type="navigate"
app-id="{{detailData.AppId}}"
path="{{detailData.Path}}"
extra-data=""
version="release"
>查看詳情</navigator>
7-3. 獲取三方小程序的APPID以及詳細(xì)頁(yè)的path
- 如何查看小程序的appid,
打開(kāi)微信 - 搜索小程序 - 進(jìn)入 - 點(diǎn)擊右上角三個(gè)點(diǎn) - 點(diǎn)擊 彈出層小程序的名稱(chēng) - 更多資料 - 即可查看 APPID - 如何獲取詳細(xì)頁(yè)的鏈接
登錄后臺(tái) - 工具 - 生成小程序碼 - 輸入小程序APPID - 獲取更多頁(yè)面路徑 - 添加自己微信號(hào) - 開(kāi)啟 ( 注:復(fù)制功能僅保留10分鐘,10分鐘后功能消失 ) - 打開(kāi)小程序詳細(xì)頁(yè) - 右上三個(gè)點(diǎn) - 選擇復(fù)制鏈接 (如果不存在,則說(shuō)明上面一步時(shí)間過(guò)期了,或沒(méi)有開(kāi)發(fā)者權(quán)限)
針對(duì)京東來(lái)說(shuō),需要將sku字段保留,其余刪除,包括".html" - 將復(fù)制的鏈接黏貼至上一步左側(cè)輸入框,生成小程序碼
- 注:如果復(fù)制鏈接,提示 【網(wǎng)絡(luò)錯(cuò)誤稍后重試】, 排除斷網(wǎng)的情況,可能是微信版本過(guò)低,重新安裝最新版本微信即可
7-4. 配置跳轉(zhuǎn)三方小程序的白名單,
在app.json內(nèi),配置navigateToMiniProgramAppIdList
補(bǔ)充說(shuō)明:
- 每個(gè)小程序可跳轉(zhuǎn)的其他小程序數(shù)量限制為不超過(guò) 10 個(gè) 從 2.4.0 版本以及指定日期(具體待定)開(kāi)始,開(kāi)發(fā)者提交新版小程序代碼時(shí),如使用了跳轉(zhuǎn)其他小程序功能,則需要在代碼配置中聲明將要跳轉(zhuǎn)的小程序名單,限定不超過(guò) 10 個(gè),否則將無(wú)法通過(guò)審核。
- 該名單可在發(fā)布新版時(shí)更新,不支持動(dòng)態(tài)修改。
- 轉(zhuǎn)發(fā)以及分享到朋友圈
轉(zhuǎn)發(fā)的觸發(fā)方式為,wxml內(nèi)放入一個(gè)button,open-type,此外在頁(yè)面的js內(nèi)要定義onShareAppMessage與onShareTimeline,分別用來(lái)定義轉(zhuǎn)發(fā)和分享到朋友圈
//用戶(hù)點(diǎn)擊右上角轉(zhuǎn)發(fā) 圖片長(zhǎng)寬比是 5:4
//基礎(chǔ)庫(kù) 1.2.0 開(kāi)始支持,低版本需做兼容處理
onShareAppMessage(res){
//兼容
var version = wx.getSystemInfoSync().SDKVersion;
var _btn = app.compareVersion(version,'1.2.0');
if(_btn){
// 來(lái)自頁(yè)面內(nèi)轉(zhuǎn)發(fā)按鈕
if(res.from === 'button'){};
return {
'title': res.target.dataset.tit || app.globalData.shareObj.sharemes,
'path': res.target.dataset.path || app.globalData.shareObj.sharePath,
'imageUrl': app.globalData.shareObj.shareSendPic
}
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用該功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
},
//用戶(hù)點(diǎn)擊右上角轉(zhuǎn)發(fā)到朋友圈 query-當(dāng)前頁(yè)面路徑攜帶的參數(shù) 圖片長(zhǎng)寬比是 1:1
//從基礎(chǔ)庫(kù) 2.11.3 開(kāi)始支持
onShareTimeline(){
//兼容
var version = wx.getSystemInfoSync().SDKVersion;
var _btn = app.compareVersion(version,'2.11.3');
if(_btn){
return {
'title': app.globalData.shareObj.sharemes,
'query': null,
'imageUrl': app.globalData.shareObj.shareFriendPic
}
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用該功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
},
注: 分享的圖片比例分別為 5:4、1:1 (可以是本地文件路徑、代碼包文件路徑或者網(wǎng)絡(luò)圖片路徑。支持PNG及JPG)
在wxml內(nèi)調(diào)用,添加自定義屬性,可能會(huì)方便些
<button
class="insetBtn"
open-type="share"
data-tit="{{listsData[nowIndex].tit}}"
data-path="/pages/find_food_detail/index?sendindex={{nowIndex}}"
></button>
- 通過(guò)坐標(biāo),打開(kāi)微信小程序內(nèi)置地圖,進(jìn)行導(dǎo)航
//使用微信內(nèi)置地圖查看位置
openLocationFn(_lat,_lon,sucFn,errFn){
if(_lat=='' || _lon==''){
this.showPopFn({
'title': '坐標(biāo)錯(cuò)誤'
});
return false;
}else{
wx.openLocation({
'latitude': _lat,
'longitude': _lon,
'scale': 17,
success(res){
sucFn && sucFn(res);
},
fail(err){
errFn && errFn(err);
}
});
};
}
調(diào)用
goOpenLocationFn(){
app.openLocationFn(30.91185865822398,120.50376582713723,null,function(err){
console.log(err);
app.showPopFn({
'title': '調(diào)用失敗',
'icon': 'success',
'duration': 500
})
})
}
- 小程序音頻使用
聲明音頻對(duì)象
var version = wx.getSystemInfoSync().SDKVersion;
var _btn = app.compareVersion(version,'1.6.0');
if(_btn){
InnerAudioContext = wx.createInnerAudioContext();
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用音頻功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
配置音頻屬性,以及調(diào)用方法
//監(jiān)聽(tīng)播放結(jié)束后,關(guān)閉對(duì)播放結(jié)束的監(jiān)聽(tīng)
InnerAudioContext.src = _nowAudioSrc;
InnerAudioContext.play()
InnerAudioContext.onEnded(function(){
InnerAudioContext.offEnded();
InnerAudioContext.stop();
...業(yè)務(wù)樣式等操作...
console.log('播放完畢');
});
注: 上述監(jiān)聽(tīng)結(jié)束的方法,最好結(jié)束后調(diào)用stop,重置音頻
10-1. 播放進(jìn)度與獲取音頻時(shí)長(zhǎng)
//2. 監(jiān)聽(tīng)播放、并獲取音頻的時(shí)長(zhǎng)、播放位置與 進(jìn)度百分比
nowAudioObj.offPlay();
nowAudioObj.onPlay(() => {
//獲取總時(shí)長(zhǎng)與當(dāng)前播放位置
nowAudioObj.offTimeUpdate();
nowAudioObj.onTimeUpdate(()=>{
//初始化 -- 獲取音頻總時(shí)長(zhǎng)
_listsData[_index].audio.duration = nowAudioObj.duration;
//實(shí)時(shí)更新 -- 獲取當(dāng)前播放的位置
_listsData[_index].audio.startTime = nowAudioObj.currentTime;
//實(shí)時(shí)更新 -- 進(jìn)度條百分比
_listsData[_index].audio.nowTimePercent = Math.floor(nowAudioObj.currentTime/nowAudioObj.duration*100);
_that.setData({
'listsData': _listsData
});
});
});
//3. 播放結(jié)束監(jiān)聽(tīng)
nowAudioObj.offEnded();
nowAudioObj.onEnded(() => {
//重置播放位置、重置樣式
_listsData[_index].audio.startTime = 0;
_listsData[_index].audio.nowTimePercent = Math.floor(0/nowAudioObj.duration*100);
_listsData[_index].audio.playStatue = false;
app.showPopFn({
'title': '播放完畢'
});
//停止監(jiān)聽(tīng)
nowAudioObj.stop();
nowAudioObj.offPlay();
nowAudioObj.offEnded();
nowAudioObj.offTimeUpdate();
_that.setData({
'listsData': _listsData
});
});
//4. 捕獲錯(cuò)誤
nowAudioObj.offError();
nowAudioObj.onError(function(errMsg,errCode){
console.log(errMsg);
var _errMes = '';
switch(errCode){
case 10001:
_errMes = '系統(tǒng)錯(cuò)誤';
break;
case 10002:
_errMes = '網(wǎng)絡(luò)錯(cuò)誤';
break;
case 10003:
_errMes = '文件錯(cuò)誤';
break;
case 10004:
_errMes = '格式錯(cuò)誤';
break;
case -1:
_errMes = '未知錯(cuò)誤';
break;
};
app.showPopFn({
title:_errMes,
duration:600
});
});
注:
- 音頻不能使用 中文名字 ,否則不能被捕獲報(bào)錯(cuò)信息
- 音頻在頁(yè)面之前切換不可以停止,所以在切換頁(yè)面之前,需要關(guān)閉音頻,
onHide -- wx.navigateTo 或 底部tab切換到其他頁(yè)面觸發(fā)
onUnload -- wx.redirectTo 或 wx.navigateBack時(shí)候觸發(fā)
- 輸入框表單,通過(guò)鍵盤(pán)進(jìn)行搜索,而非一個(gè)自定義按鈕
通過(guò)bindconfirm事件,可以在鍵盤(pán)敲擊回車(chē)、在手機(jī)鍵盤(pán)輸入法觸摸完成后,即可進(jìn)行搜索
<input
type="text"
bindinput="txtFn"
bindconfirm="inputConfirmFn"
value="{{txtval}}"
placeholder="搜索內(nèi)容..."
/>
通過(guò)事件對(duì)象 ev.detail.value 可以完成內(nèi)容獲取
inputConfirmFn(ev){
var _val = ev.detail.value;
_val = _val.replace(/\s+/g,"");
if(_val != ''){
console.log('提交的內(nèi)容為',_val);
}else{
app.showPopFn({
'title': '內(nèi)容不能為空',
'icon': 'none',
'duration': 600
});
};
}
- 小程序自帶的頂部工具欄,可以通過(guò)在app.json的window內(nèi),通過(guò)"navigationStyle":"custom"關(guān)閉默認(rèn)導(dǎo)航
只保留右上角三個(gè)點(diǎn)
"navigationStyle":"custom"
定義一個(gè)自定義狀態(tài)欄組件,可以使用的屬性與插槽,官方手冊(cè) - https://developers.weixin.qq.com/miniprogram/dev/extended/weui/navigation.html
問(wèn)題:
不同設(shè)備的狀態(tài)欄的高度不一樣,因此自定義導(dǎo)航圖標(biāo),可能會(huì)因設(shè)備不一樣而跑偏,
所以,為了統(tǒng)一這個(gè)比例,可以通過(guò)wx.getSystemInfo獲取系統(tǒng)信息,通過(guò)系統(tǒng)信息返回statusBarHeight獲得狀態(tài)欄高度( 單位px )
再通過(guò) wx.getMenuButtonBoundingClientRect()方式是獲得膠囊按鈕的空間信息,以及系統(tǒng)狀態(tài)欄的高度,之后進(jìn)行對(duì)應(yīng)的計(jì)算
【注】:getMenuButtonBoundingClientRect 部分手機(jī)有獲取設(shè)備 信息延遲 - https://developers.weixin.qq.com/community/develop/doc/0006eeb2db0ae022a098c58f85d800,所以官方建議加100MS延遲,等待信息!
具體的方法是:
app.js onLaunch聲明周期中
//獲取狀態(tài)欄高度
wx.getSystemInfo({
success(res){
_that.globalData.sysBarHeight = res.statusBarHeight;
console.log(res.statusBarHeight);
},
fail(err){
console.log('系統(tǒng)信息錯(cuò)誤',err);
}
});
//獲取膠囊按鈕的空間信息
//基礎(chǔ)庫(kù) 2.1.0 開(kāi)始支持
if(_that.compareVersion(version,'2.1.0')){
var ButtonBoundingRes = wx.getMenuButtonBoundingClientRect();
if(ButtonBoundingRes){
_that.globalData.ButtonBoundingHright = (ButtonBoundingRes.top - _statusBarHeight)*2 + ButtonBoundingRes.height
};
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法獲取膠囊按鈕尺寸功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};

通過(guò)上面方式計(jì)算結(jié)果 自定義導(dǎo)航欄的高度應(yīng)該為
| statusBarHeight | 下面的膠囊實(shí)際占位 | 最終自定義導(dǎo)航高度 |
|---|---|---|
| 20 | (24-20)*2+32 | 60 |
20 + (24-20)*2+32 = 60
上面計(jì)算的單位為px,如果在頁(yè)面內(nèi)使用,需要使用rpx,因?yàn)閜x是固定值,不同手機(jī)設(shè)備高度不一,可能引起適配問(wèn)題:
在app.js的onLaunch生命周期內(nèi),獲取當(dāng)前設(shè)備的px與rpx比例,將px轉(zhuǎn)化為rpx,在頁(yè)面內(nèi)使用更精準(zhǔn)些
var _windowWidth = wx.getSystemInfoSync().windowWidth
var _rate = 750 / _windowWidth
_that.globalData.rateRpx = _rate;
- 小程序組件lifetimes 可以補(bǔ)充onload、onshow的生命周期
js
lifetimes: {
attached: function() {
// 在組件實(shí)例進(jìn)入頁(yè)面節(jié)點(diǎn)樹(shù)時(shí)執(zhí)行
...
},
detached: function() {
// 在組件實(shí)例被從頁(yè)面節(jié)點(diǎn)樹(shù)移除時(shí)執(zhí)行
...
},
},
- 通過(guò)分享進(jìn)來(lái),沒(méi)有返回主頁(yè)入口的困局
問(wèn)題:
如果分享頁(yè)面是詳細(xì)頁(yè)面,通過(guò)分享點(diǎn)擊進(jìn)來(lái),無(wú)法通過(guò)常規(guī)后退按鈕返回,因此需要一個(gè)返回首頁(yè)的按鈕
但是需要一個(gè)判斷的條件,即 如何判斷此時(shí)頁(yè)面是否為分享點(diǎn)擊進(jìn)來(lái)的。
方案:
在app.js內(nèi),可以在App的onLaunch和onShow,或wx.getLaunchOptionsSync中獲取上述場(chǎng)景值,
來(lái)獲取 scene (小程序的場(chǎng)景值)
官方的場(chǎng)景值對(duì)應(yīng)表 -https://developers.weixin.qq.com/miniprogram/dev/reference/scene-list.html
通過(guò)將獲取的scene來(lái)判斷是否顯示一個(gè)返回主頁(yè)的入口,與表格對(duì)比可知,
1007 -- 是分享給朋友,朋友通過(guò)鏈接點(diǎn)擊過(guò)來(lái)的
1008 -- 群聊會(huì)話(huà)中的小程序消息卡片
app.js
App({
onLaunch(option){
//可以查看scene值
if(option.scene==1007 || option.scene==1008){
_that.globalData.formShare = true;
};
...
pages/xx/xx.wxml內(nèi)
<!-- 后退 -->
<view
wx:if="{{!homeBackBtn}}"
bindtap="backFn"
class="backIcon"
>
<view class="icoInset iconTag backIco"></view>
</view>
<!-- 返回首頁(yè) -->
<view
wx:else
bindtap="backHomeFn"
class="backIcon"
>
<view class="icoInset iconTag homeIco"></view>
</view>
pages/xx/xx.js內(nèi)
onLoad:function(option){
//是否顯示返回主頁(yè)按鈕
if(app.globalData.formShare){
_that.setData({
'homeBackBtn': true
})
};
},
backHomeFn(){
//重置狀態(tài)
app.globalData.formShare = false;
this.setData({
'homeBackBtn': false
});
//完成跳轉(zhuǎn)
app.returnHomeFn();
}
- wx.navigateTo 與 wx.redirectTo 的使用差異
不同點(diǎn):
wx.navigateTo 用于頁(yè)面流程為串行的操作,最多紀(jì)錄10層歷史路徑,可以通過(guò)wx.navigateBack進(jìn)行后退,
如果超過(guò)10層,會(huì)進(jìn)行報(bào)錯(cuò)。
navigateTo webview cont limit exceed
wx.redirectTo 可以用來(lái)代替上頁(yè)面跳轉(zhuǎn)的問(wèn)題,但是無(wú)法使用歷史路徑。
相同點(diǎn):
都不能跳到 tabbar 頁(yè)面
- 復(fù)雜數(shù)據(jù)的修改,通過(guò)字符串拼接好數(shù)據(jù),包裹上[ ]來(lái)進(jìn)行解析
推薦的方式:
var _nowIndex = this.data.nowIndex;
this.setData({
['listsData['+_nowIndex+'].sonIndex']: 新的數(shù)據(jù)
});
或
var _dataStr = "mapDatas.tabLists["+_mapDatas.tabIndex+"].sonLists";
_that.setData({
[_dataStr]: _tempArr
});
引起問(wèn)題的方式:
var _sonIndex = ev.detail.current;
var _listsData = this.data.listsData;
var _nowIndex = this.data.nowIndex;
_listsData[_nowIndex].sonIndex = _sonIndex;
this.setData({
'listsData': _listsData
});
出現(xiàn)的具體問(wèn)題是:
- listsData下某個(gè)無(wú)需修改數(shù)據(jù),重新覆蓋,會(huì)引起undefined的渲染錯(cuò)誤,比如地圖組件的經(jīng)緯度;
- 此外對(duì)局部的數(shù)據(jù)修改,是被建議的
- 渲染大小的建議
由于小程序運(yùn)行邏輯線(xiàn)程與渲染線(xiàn)程之上,setData的調(diào)用會(huì)把數(shù)據(jù)從邏輯層傳到渲染層,數(shù)據(jù)太大會(huì)增加通信時(shí)間。
**得分條件:`setData`的數(shù)據(jù)在`JSON.stringify`后不超過(guò) 256KB**
scroll-view組件內(nèi),存在子元素,包裹一個(gè)swiper組件和同級(jí)增加一個(gè)浮層,滾動(dòng)scroll-view時(shí)候,浮層會(huì)消失
解決方法:
將浮層從swiper同級(jí)提取到更高一層,可以解決問(wèn)題。wx.navigateTo跳轉(zhuǎn),會(huì)出現(xiàn)重復(fù)跳轉(zhuǎn)
原因:如 wx.navigateTo、wx.redirectTo跳轉(zhuǎn)官方?jīng)]有做節(jié)流
具體操作:
//修復(fù)BUG、節(jié)流timer
var navigaterTimer = null;
var redirectTimer = null;
App({
onLaunch(option){
var _that = this;
...
//跳轉(zhuǎn) wx.navigateTo 小程序中頁(yè)面棧最多十層
jumpLink(_link,sucFn,errFn){
clearTimeout(navigaterTimer);
navigaterTimer = setTimeout(function(){
wx.navigateTo({
url: _link,
success(res){
sucFn && sucFn(res);
},
fail(err){
errFn && errFn(err);
}
})
},600);
},
//跳轉(zhuǎn)
jumpLink2(_link,sucFn,errFn){
clearTimeout(redirectTimer);
redirectTimer = setTimeout(function(){
wx.redirectTo({
url: _link,
success(res){
sucFn && sucFn(res);
},
fail(err){
errFn && errFn(err);
}
});
},500);
},
注:延遲時(shí)間越久,修復(fù)效果越好,如果延遲時(shí)間設(shè)置300ms,在模擬器上仍可能出現(xiàn)重復(fù)跳轉(zhuǎn)的情況,理解可能是設(shè)備性能來(lái)不及反應(yīng)?
text標(biāo)簽內(nèi)如果要添加長(zhǎng)文本,為了方便用戶(hù)瀏覽時(shí)copy可以,為text添加user-select屬性,
此外,首行縮進(jìn)(text-indent:2em;)不能添加到父級(jí)標(biāo)簽,否則會(huì)溢出屏幕針對(duì)富文本,處理帶有HTML標(biāo)簽的文案
<rich-text nodes="{{itemEle.backMes.detmes}}" user-select></rich-text>
- 獲取rpx與px的轉(zhuǎn)化比例值
已知:小程序規(guī)定屏幕寬為750rpx,這個(gè)無(wú)關(guān)機(jī)型(rpx(responsive pixel): 可以根據(jù)屏幕寬度進(jìn)行自適應(yīng))
未知:當(dāng)前設(shè)備的寬度
let windowWidth = wx.getSystemInfoSync().windowWidth
let rate = 750 / windowWidth
-
小程序加載分頁(yè)的格式
小程序分頁(yè)流程圖
22-2. 分頁(yè)代碼格式
js:
'commentLists':{
'list':[],
'loaded': false,
'isLoading': false,
'noMore': false,
'totalcount':0,
'pageindex': 0
}
wxml:
<!--加載完畢-->
<view
class="commentLists"
wx:if="{{isLoaded}}"
>
<!-- 有數(shù)據(jù) -->
<view
wx:if="{{commentLists.list.length>0}}"
>
<!--數(shù)據(jù)列表-->
<view class="listBox">
<!-- ele -->
<view
class="ele"
wx:for="{{commentLists.list}}"
wx:for-index="idx"
wx:for-item="itemEle"
wx:key="idx"
>
<view class="phootBox borderR">
<image src="{{itemEle.userPhoto}}" mode="aspectFill" />
</view>
<view class="say">
<text>{{itemEle.mes}}</text>
</view>
</view>
</view>
<!-- 暫無(wú)更多數(shù)據(jù) -->
<view wx:if="{{noMore}}" class="noDataTxt">
<text>暫無(wú)更多評(píng)論</text>
</view>
</view>
<!-- 無(wú)數(shù)據(jù) -->
<view wx:if="{{commentLists.noMore}}">
<view class="noDataTxt">
<text>暫無(wú)任何數(shù)據(jù)</text>
</view>
</view>
</view>
<!--加載中-->
<view wx:else>
<view class="noDataTxt">
<text>加載中...</text>
</view>
</view>
- 小程序跳轉(zhuǎn)第三方小程序中某個(gè)頁(yè)面
具體流程:
- 配置app.json ---(已經(jīng)廢棄)
小程序限定不超過(guò)10個(gè),否則將無(wú)法通過(guò)審核。
此名單可在發(fā)布新版時(shí)更新,不支持動(dòng)態(tài)修改。
"navigateToMiniProgramAppIdList": [
"wx91d27dbf599dff74",
"wx0e6ed4f51db9d078"
]
備注:
從2020年4月24日起,使用跳轉(zhuǎn)其他小程序功能將無(wú)需在全局配置中聲明跳轉(zhuǎn)名單 ,跳轉(zhuǎn)其他小程序?qū)⒉辉偈軘?shù)量限制
- 獲取跳轉(zhuǎn)小程序的appid
微信 - 搜索小程序 京東 - 打開(kāi)小程序 - 右上角三個(gè)點(diǎn) - 點(diǎn)擊浮層內(nèi)小程序名稱(chēng) - 更多資料 - 點(diǎn)擊即可查看AppID - 查看該商品是否可以獲取詳情地址,
打開(kāi)要跳轉(zhuǎn)的小程序目標(biāo)頁(yè)面,右上角三個(gè)點(diǎn),發(fā)送給朋友,
如果點(diǎn)擊這個(gè)鏈接可以達(dá)到目前鏈接,則繼續(xù)后續(xù)步驟。
如果僅能跳轉(zhuǎn)至目標(biāo)小程序的首頁(yè),那么說(shuō)明無(wú)法獲取商品詳情地址,則可以停止后續(xù)流程了 -
打開(kāi)微信公眾平臺(tái),登錄賬號(hào)后,頂部菜單 工具-生成小程序碼,將上面獲取的appid輸入,搜索小程序;
然后將自己的小程序賬號(hào)放進(jìn)去,點(diǎn)擊"開(kāi)啟"即可顯示復(fù)制鏈接按鈕;
【注】: 這個(gè)"開(kāi)啟"按鈕有一個(gè)有效時(shí)間,過(guò)了時(shí)間就不顯示復(fù)制鏈接按鈕了,需要再次這一步開(kāi)啟
配置微信的截圖
上面開(kāi)啟有時(shí)間限制,如果過(guò)了一段時(shí)間,跳轉(zhuǎn)的小程序內(nèi),點(diǎn)擊右上角三個(gè)點(diǎn),彈出層內(nèi)可能會(huì)不顯示"復(fù)制鏈接"
- 編輯鏈接地址
點(diǎn)擊這個(gè)分享的圖文框,再點(diǎn)擊右上角的三個(gè)點(diǎn),浮層內(nèi),點(diǎn)擊復(fù)制鏈接;
將復(fù)制的鏈接,在記事本內(nèi)編輯,刪除.html與id參數(shù)之后的內(nèi)容;
例如:
pages/gs/sight/newDetail.html?sightId=25603&mktshare=eyJhbGxpYW2IjNyojIklWZj5ODQsInNpZCI6NzExNDY1LCJvdWlkIjoiIiwic291cmNlaWQiOjU1NTUyNjg5LCJmcm9tYWxsaWFuY2VpZCI6MCwiZnJvbXNpZCI6MCwiZnJvbW91aWQiOiIiLCJmcm9tc291cmNlaWQiOjAsImZyb21vcGVuaWQiOiIyMTVhZGVhZi1lMmRiLTQ3YWUtODRiZC1hMWU2ZWViMWNlMTAifQ()()KY&allianceid=262684&sid=711465&ouid=&sourceid=55552689
處理鏈接為:
pages/gs/sight/newDetail?sightId=25603
wxml標(biāo)簽內(nèi)使用,方式為:
<navigator
target="miniProgram"
open-type="navigate"
app-id="{{pageDetail.appid}}"
path="{{pageDetail.path}}"
extra-data=""
version="release"
>查看詳情</navigator>
- pinker針對(duì)數(shù)組包裹對(duì)象的形式,需要處理一份用于展示的pinker數(shù)據(jù)
- 原始數(shù)據(jù):
deptData:{
indexnum:0,
list: [
{ id:1, name:'服裝藝術(shù)與工程學(xué)院' },
{ id:2, name:'材料設(shè)計(jì)與工程學(xué)院' }
]
}
- 處理后數(shù)據(jù):
deptData:{
indexnum:0,
list: [
{ id:1, name:'服裝藝術(shù)與工程學(xué)院' },
{ id:2, name:'材料設(shè)計(jì)與工程學(xué)院' }
],
pinkerlist: [
'服裝藝術(shù)與工程學(xué)院','材料設(shè)計(jì)與工程學(xué)院'
]
}
結(jié)構(gòu):
--wxml--
<picker
class="pickerBox"
bindchange="changeDeptFn"
range="{{deptData.pinkerlist}}"
value="{{deptData.indexnum}}"
>
<view class="mes">
<text class="tit">選擇學(xué)院:</text>
<text class="pinkmes">{{deptData.pinkerlist[deptData.indexnum]}}</text>
</view>
</picker>
--js--
changeDeptFn(ev){
var _that = this;
var _indexnum = ev.detail.value;
_that.setData({
['deptData.indexnum']: _indexnum
});
//根據(jù)學(xué)院,加載專(zhuān)業(yè)
_that.getSpecDataFn();
}
- 組件的使用
組件目錄位置:同pages相同目錄的components文件夾
- 設(shè)置組件
配置組件目錄下的 .json文件
{
"usingComponents": {},
"component": true
}
- 使用組件
配置組件目錄下的 .json文件
{
"usingComponents": {
"workDetail": "/components/workdetail/index"
}
}
引入組件
<workDetail
userCollect="{{userCollect.data}}"
userData="{{userData}}"
worksid="{{worksid}}"
bind:addCollectFn="addCollectFn"
bind:delCollectFn="delCollectFn"
></workDetail>
25-1. 組件內(nèi)通信 官方鏈接 - https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html
- 父組件 -> 子組件
通過(guò)掛載屬性的方式實(shí)現(xiàn),數(shù)據(jù)掛載
//--wxml
<workDetail
bind:addCollectFn="addCollectFn"
></workDetail>
//--js
addCollectFn(e){
console.log(e.detail);
}
- 子組件 -> 父組件
//--js
this.triggerEvent('addCollectFn', _addObj);
25-2. 父組件使用子組件內(nèi)的方法
//--wxml
<workDetail id="workDetailCmp"></workDetail>
//--js
onReady(){
this.selectComponent('#workDetailCmp').fn1();
}
- 通過(guò)option設(shè)置數(shù)值,并將數(shù)據(jù)掛載至組件上,子組件內(nèi)通過(guò)properties獲取數(shù)據(jù),
在子組件的生命周期 lifetimes 的attached內(nèi)調(diào)用,存在延遲問(wèn)題
- 問(wèn)題產(chǎn)生的原因:
lifetimes 生命周期 -https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html內(nèi),attached調(diào)用,父組件掛載的數(shù)據(jù)還沒(méi)過(guò)來(lái),等父組件的數(shù)據(jù)更新后,attached內(nèi)方法不會(huì)再執(zhí)行
lifetimes: {
attached: function() {
// 在組件實(shí)例進(jìn)入頁(yè)面節(jié)點(diǎn)樹(shù)時(shí)執(zhí)行
//初始化菜單索引位置
this.getProductDetFn();
},
detached: function(){
// 在組件實(shí)例被從頁(yè)面節(jié)點(diǎn)樹(shù)移除時(shí)執(zhí)行
}
}
- 解決:
掛載的方法,可以對(duì)數(shù)據(jù)設(shè)置數(shù)據(jù)開(kāi)關(guān),等數(shù)據(jù)加載完畢后,打開(kāi)開(kāi)關(guān)進(jìn)行組件數(shù)據(jù)掛載
如:
'userCollect': {
'data': [],
'loaded': false
}
<view wx:if="{{worksid && userCollect.loaded}}">
<workDetail
userCollect="{{userCollect.data}}"
userData="{{userData}}"
worksid="{{worksid}}"
bind:addCollectFn="addCollectFn"
bind:delCollectFn="delCollectFn"
></workDetail>
</view>
- 設(shè)置數(shù)據(jù) setData 中的問(wèn)題
- 設(shè)置數(shù)據(jù)時(shí)候,如果下面書(shū)寫(xiě)會(huì)報(bào)錯(cuò)
data:{
'userCollect': {
'data': [],
'loaded': false
}
},
fn1(e){
//錯(cuò)誤
//var _userCollect = _that.data.userCollect;
//_userCollect.data.push(_tempAddObj);
//正確
var _userCollect = _that.data.userCollect.data;
_userCollect.push(_tempAddObj);
_that.setData({
['userCollect.data']: _userCollect
});
}
- webview相關(guān)
- 創(chuàng)建小程序,使用企業(yè)身份申請(qǐng),完成轉(zhuǎn)賬等身份驗(yàn)證
- 配置開(kāi)發(fā)管理-開(kāi)發(fā)設(shè)置-業(yè)務(wù)域名,下載驗(yàn)證文件,上傳至業(yè)務(wù)域名服務(wù)器的根下
- wxml添加 <web-view src="業(yè)務(wù)域名的H5文件"></web-view>
- 查看 官方文檔 -
https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html, 下載 JSSDK 1.3.2 -https://res.wx.qq.com/open/js/jweixin-1.3.2.js,以便在H5頁(yè)面內(nèi)使用小程序的API(如返回路由)
- 點(diǎn)擊事件,阻止冒泡之 catchtap
- bindtap是冒泡的
- catchtap是非冒泡的
- 監(jiān)聽(tīng)用戶(hù)上拉觸底事件
- 可以在app.json的window選項(xiàng)中或頁(yè)面配置中設(shè)置觸發(fā)距離onReachBottomDistance。
- 在觸發(fā)距離內(nèi)滑動(dòng)期間,本事件只會(huì)被觸發(fā)一次。
- onReachBottom生命周期內(nèi)處理事件
- 地圖API、組件
- 地圖組件 <map>
<map
id="myMap"
latitude="{{mapDatas.tabLists[mapDatas.tabIndex].wxMapDataList[mapDatas.sonindex].latitude}}"
longitude="{{mapDatas.tabLists[mapDatas.tabIndex].wxMapDataList[mapDatas.sonindex].longitude}}"
markers="{{mapDatas.tabLists[mapDatas.tabIndex].wxMapDataList}}"
show-location
show-compass
show-scale
bindmarkertap="bindmarkerFn"
></map>
- 地圖屬性
latitude -- 地圖中心緯度 (-90 ~ 90) - 【特別注意都是數(shù)字類(lèi)型】
longitude -- 地圖中心經(jīng)度 (-180 ~ 180) - 【特別注意都是數(shù)字類(lèi)型】
- 地圖遮蓋物點(diǎn)擊事件:bindmarkertap
- 地圖獲取上下文方法: wx.createMapContext(string mapId, Object this) -- 版本要求:1.9.6
- 地圖移動(dòng)地圖中心點(diǎn)的方法
_that.mapCtx.moveToLocation({
longitude: Number(新的中心點(diǎn)經(jīng)度),
latitude: Number(新的中心點(diǎn)緯度),
success(){},
fail(err){
console.log(err);
}
});
- 地理位置授權(quán) app.json
"permission": {
"scope.userLocation": {
"desc": "你的位置信息將用于小程序位置接口的效果展示"
}
},
- 監(jiān)聽(tīng)組件上的參數(shù)變化
//--wxml
<workDetail
userCollect="{{userCollect.data}}"
userData="{{userData}}"
worksid="{{worksid}}"
onlyRead="{{onlyRead}}"
bind:addCollectFn="addCollectFn"
bind:delCollectFn="delCollectFn"
></workDetail>
//--js
lifetimes:{
...
},
observers:{
//基礎(chǔ)庫(kù)版本 2.6.1 開(kāi)始支持
'worksid': function(newV) {
var version = wx.getSystemInfoSync().SDKVersion;
var _btn = app.compareVersion(version,'2.6.1');
if(_btn){
// console.log(newV);
//加載作品詳情
this.getProductDetFn();
}else{
wx.showModal({
title: '提示',
content: '當(dāng)前微信版本過(guò)低,無(wú)法使用該功能,請(qǐng)升級(jí)到最新微信版本后重試。'
});
};
}
}
- 頁(yè)面渲染截?cái)嗟那闆r
- 產(chǎn)生原因:
setData接口的調(diào)用涉及邏輯層與渲染層間的線(xiàn)程通信,通信過(guò)于頻繁可能導(dǎo)致處理隊(duì)列阻塞,界面渲染不及時(shí)而導(dǎo)致卡頓,應(yīng)避免無(wú)用的頻繁調(diào)用。 - 解決方案:
每秒調(diào)用setData的次數(shù)不超過(guò) 20 次
-
小程序頁(yè)面性能監(jiān)測(cè) 官方地址 -
https://developers.weixin.qq.com/miniprogram/dev/framework/audits/best-practice.html
小程序開(kāi)發(fā)工具 在調(diào)試器區(qū)域切換到 Audits 面板,
點(diǎn)擊”開(kāi)始“按鈕,然后自行操作小程序界面,運(yùn)行過(guò)的頁(yè)面就會(huì)被“體驗(yàn)評(píng)分”檢測(cè)到。
性能分析工具截圖 小程序獲取用戶(hù)信息 新要求
推薦使用 wx.getUserProfile ,不推薦使用getUserInfo
具體范例:
- 不推薦使用getUserInfo獲取用戶(hù)信息,預(yù)計(jì)自2021年4月13日起,getUserInfo將不再?gòu)棾鰪棿?,并直接返回匿名的用?hù)個(gè)人信息
如下:
<button wx:else open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 獲取頭像昵稱(chēng) </button>
- 推薦使用wx.getUserProfile獲取用戶(hù)信息,開(kāi)發(fā)者每次通過(guò)該接口獲取用戶(hù)個(gè)人信息均需用戶(hù)確認(rèn)
//--wxml
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 獲取頭像昵稱(chēng) </button>
//--js
onLoad() {
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile(e) {
// 推薦使用wx.getUserProfile獲取用戶(hù)信息,開(kāi)發(fā)者每次通過(guò)該接口獲取用戶(hù)個(gè)人信息均需用戶(hù)確認(rèn)
// 開(kāi)發(fā)者妥善保管用戶(hù)快速填寫(xiě)的頭像昵稱(chēng),避免重復(fù)彈窗
wx.getUserProfile({
desc: '用于完善會(huì)員資料', // 聲明獲取用戶(hù)個(gè)人信息后的用途,后續(xù)會(huì)展示在彈窗中,請(qǐng)謹(jǐn)慎填寫(xiě)
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
- 一個(gè)兩列的瀑布流如何實(shí)現(xiàn),(支持分頁(yè))
- 原理:
第一步,將一個(gè)數(shù)據(jù)列表,拆為兩個(gè)數(shù)據(jù)列表,并定義兩個(gè)列表的初始高度
第二步,每次請(qǐng)求后臺(tái)獲取過(guò)來(lái)的數(shù)據(jù),對(duì)比一下兩列累積高度,哪一側(cè)小,就優(yōu)先將數(shù)據(jù)插入至哪一側(cè),并將對(duì)應(yīng)側(cè)的高度累加
第三步,將更新后的兩列數(shù)據(jù)以及累加后的兩個(gè)高度值,返回
第四步,與后臺(tái)接口開(kāi)發(fā)人員,提前告知返回圖片寬、高 字段(如例子中的ImgWidth,ImgHeight),用于計(jì)算列表高度使用
注:
第一,由于列表高度考量因素是圖片高度,如果列表單元,是一個(gè)圖文配,那么需要將文字部分設(shè)置統(tǒng)一高度,文字溢出省略號(hào),才可以(單行省略號(hào)或多行省略號(hào))
目的還是將判斷哪一列插入數(shù)據(jù)的考量,縮小為圖片高度一個(gè)判斷依據(jù)
第二,瀑布流中兩列的寬度必須一致(如列中:375屏寬下,單列162rpx寬),否則兩列寬度不統(tǒng)一,通過(guò)圖片(widthFix模式)獲取的等比高度,將不能用于判斷
- 數(shù)據(jù)結(jié)構(gòu):
'mainNews':{
'loaded': false,
'isLoading': false,
'noMore': false,
'totalcount':0,
'pageindex': 0,
/*變量名代表:左側(cè)數(shù)據(jù)列表,右側(cè)數(shù)據(jù)列表,左側(cè)列表累積高度,右側(cè)列表累積高度*/
'listL': [],
'listR': [],
'leftNowH':0,
'rightNowH':0
},
- 全局app.js內(nèi),工具函數(shù)
/*瀑布流排序 - 計(jì)算高度,重新排序
* 如果存在分頁(yè)
* 傳入值: datalist- 待處理數(shù)據(jù) | oldLeftH- 舊的左側(cè)高度 | oldRightH- 舊的右側(cè)高度
* 輸出值: leftArr- 左側(cè)數(shù)據(jù) | rightArr- 右側(cè)數(shù)據(jù) | leftNowH - 左側(cè)累積值 | rightNowH - 右側(cè)累計(jì)值
*/
sortListFn(datalist,oldLeftH,oldRightH){
var _leftH = oldLeftH || 0;
var _rightH = oldRightH || 0;
var _leftArr = [];
var _rightArr = [];
datalist.forEach(function(item,index){
//162(rpx)為一個(gè)頁(yè)面布局寬度,計(jì)算值為布局寬度內(nèi)的圖片高度,僅比大小,不用那么精細(xì)
var _layoutH = Math.ceil((item.ImgHeight*162)/item.ImgWidth);
if(_leftH>_rightH){
_rightArr.push(datalist[index]);
_rightH+=_layoutH;
}else{
_leftArr.push(datalist[index]);
_leftH+=_layoutH;
};
});
//每次更新后的,兩側(cè)累積高度:
//console.log(_leftH,_rightH);
return {
leftArr: _leftArr,
rightArr: _rightArr,
leftNowH: _leftH,
rightNowH: _rightH
};
}
- 如何使用工具函數(shù)
... 某事件回調(diào)內(nèi)
var _that = this;
_that.getDataFn(function(res){
var _mainNews = _that.data.mainNews;
var _sortRes = app.sortListFn(res.data.list,_mainNews.leftNowH,_mainNews.rightNowH);
var _listL = _mainNews.listL.concat(_sortRes.leftArr);
var _listR = _mainNews.listR.concat(_sortRes.rightArr);
//有無(wú)更多數(shù)據(jù)
var _totalcount = res.data.totalcount;
//設(shè)置數(shù)據(jù)
_that.setData({
["mainNews.listL"]: _listL,
["mainNews.listR"]: _listR,
["mainNews.leftNowH"]: _sortRes.leftNowH,
["mainNews.rightNowH"]: _sortRes.rightNowH,
["mainNews.loaded"]: true,
["mainNews.totalcount"]: _totalcount
});
//有無(wú)更多數(shù)據(jù)
if((_listL.length+_listR.length) == _totalcount){
_that.setData({
["mainNews.noMore"]: true
});
}else{
_that.setData({
["mainNews.noMore"]: false
});
};
},function(err){
console.log(err);
});
...
- 通過(guò)微信生成小程序二維碼,然后掃碼進(jìn)入小程序,并傳遞參數(shù)的實(shí)現(xiàn)
后端:
{
"page": "pages/index/index",
"scene": "a=1",
"check_path": true,
"env_version": "release"
}
注意:
- 開(kāi)發(fā)環(huán)境要對(duì)應(yīng)上 env_version 正式版為 "release",體驗(yàn)版為 "trial",開(kāi)發(fā)版為 "develop"。默認(rèn)是正式版。
- 踩坑,不要在連接地址上使用下劃線(xiàn)'_',否則會(huì)獲取不到參數(shù),如:'pages/index/index',不能寫(xiě)成 'pages/abc_index/index'
前端:
在掃碼對(duì)應(yīng)的頁(yè)面內(nèi),onload聲明周期中獲取參數(shù),參數(shù)在scene中,這個(gè)scene不是app.js的onlunch的場(chǎng)景值,而是一個(gè)掃碼進(jìn)入某個(gè)頁(yè)面的參數(shù)載體
Page({
onLoad (query) {
// scene 需要使用 decodeURIComponent 才能獲取到生成二維碼時(shí)傳入的 scene
const scene = decodeURIComponent(query.scene)
}
})
此外,調(diào)試的時(shí)候,可以通過(guò)開(kāi)發(fā)者工具,掃描為了開(kāi)發(fā)板生成的二維碼,實(shí)現(xiàn)本地調(diào)試功能

- 小程序內(nèi)調(diào)用掃一掃功能
wx.scanCode({
// 只允許從相機(jī)掃碼
onlyFromCamera: true,
// 掃碼類(lèi)型 - 二維碼
scanType: qrCode,
success (res.path) {
var _resPath = decodeURIComponent(res.path);
console.log(_resPath );
}
})
開(kāi)發(fā)者工具,通過(guò)上面API,可以直接上傳掃碼的圖片,完成掃碼,數(shù)據(jù)格式如下:

占坑....


