微信提供的開發(fā)工具的編輯功能不是一般的水,寫代碼肯定不能用它,否則就是浪費(fèi)生命.不說(shuō)別的,連自動(dòng)保存都沒(méi)有,第一次寫時(shí)寫了一個(gè)多小時(shí),后面下班直接關(guān)掉,也不彈出提示說(shuō)沒(méi)保存.然后第二天過(guò)來(lái),寫的代碼全沒(méi)了!!! 頓時(shí)感到巨坑無(wú)比.這些工具開發(fā)人員吃干飯的么???
(后來(lái)的版本已經(jīng)修復(fù)不能自動(dòng)保存的問(wèn)題了,當(dāng)然編輯功能還是不好用.)
它的正確用法是作為運(yùn)行和調(diào)試工具.
那么適合作為編輯工具的是: webStorm.基于IntelJ內(nèi)核,開啟Dracula主題,跟Android studio的使用習(xí)慣非常接近,so cool!各種方法提示,自動(dòng)保存,快速查找...應(yīng)有盡有.閉源的微信開發(fā)工具就不要用來(lái)寫代碼了,珍惜生命.
webStorm要識(shí)別wxml和wxss,還需要配置一下文件類型:(看下面別人截的圖)
記住html和css里都要加上微信小程序?qū)?yīng)的類型

綜上,開發(fā)時(shí),用webstorm來(lái)寫代碼,用微信開發(fā)工具來(lái)運(yùn)行和調(diào)試,速度颼颼的!
微信提供了底層網(wǎng)絡(luò)驅(qū)動(dòng)以及成功和失敗的回調(diào).但對(duì)于一個(gè)項(xiàng)目中的實(shí)際使用而言,仍然還是顯得繁瑣,還有很多封裝和簡(jiǎn)化的空間.
wx.request({
url: 'test.php',//請(qǐng)求的url
data: {//請(qǐng)求的參數(shù)
x: '' ,
y: ''
},
header: {//請(qǐng)求頭
'Content-Type': 'application/json'
},
method:"POST",
success: function(res) {//成功的回調(diào)
console.log(res.data)
}
})
對(duì)于一個(gè)網(wǎng)絡(luò)訪問(wèn)來(lái)說(shuō),請(qǐng)求一般是get和post,拼上各種參數(shù)以及請(qǐng)求頭,然后拿到回來(lái)的響應(yīng),解析并得到最終需要的數(shù)據(jù).
對(duì)于具體項(xiàng)目來(lái)說(shuō),請(qǐng)求時(shí)會(huì)有每個(gè)(或大多數(shù))請(qǐng)求都要帶的參數(shù),都要帶的請(qǐng)求頭,返回的數(shù)據(jù)格式可能都是一致的,那么基于此,對(duì)微信的網(wǎng)絡(luò)請(qǐng)求api進(jìn)行二次封裝:
在我目前的項(xiàng)目中,
大多數(shù)請(qǐng)求是post,基本上每個(gè)請(qǐng)求都需要攜帶sessionId來(lái)與服務(wù)器驗(yàn)證登錄狀態(tài),還有很多請(qǐng)求是基于分頁(yè)的,需要帶上pageSize和pageIndex.
再跟頁(yè)面邏輯關(guān)聯(lián)起來(lái),請(qǐng)求可能是因?yàn)榈谝淮芜M(jìn)入頁(yè)面,或者刷新,或者上拉加載更多.
大多數(shù)拿到的數(shù)據(jù)格式是標(biāo)準(zhǔn)json格式,如下
{
"code":1,
"data":xxx,//可能是String,也可能是JsonObject,或JsonArray,也可能是null,或undefined
"msg":yyy//可能為空
}
通過(guò)請(qǐng)求的狀態(tài)碼code來(lái)判斷這個(gè)請(qǐng)求是否真正成功.我們的項(xiàng)目中還有常見的是code=5:登錄過(guò)期或未登錄,code=2: 沒(méi)有找到對(duì)應(yīng)的內(nèi)容 等等.
如果是大多數(shù)情況的請(qǐng)求時(shí),只需要指定:
對(duì)于響應(yīng),我們只需要:
我們期望的api是:
netUtil.buildRequest(page,urlTail,params,callback)//必須的參數(shù)和回調(diào)
.setXxx(xxx)//額外的設(shè)置,鏈?zhǔn)秸{(diào)用
..
.send();//最終發(fā)出請(qǐng)求的動(dòng)作
//這兩個(gè)錯(cuò)誤碼是項(xiàng)目接口文檔統(tǒng)一定義好的
const code_unlogin = 5;
const code_unfound = 2;
function requestConfig(){
this.page; //頁(yè)面對(duì)象
this.isNewApi = true;
this.urlTail='';
this.params={
pageIndex:0,
pageSize:getApp().globalData.defaultPageSize,
session_id:getApp().globalData.session_id
};
this.netMethod='POST';
this.callback={
onPre: function(){},
onEnd: function(){
},
onSuccess:function (data){},
onEmpty : function(){},
onError : function(msgCanShow,code,hiddenMsg){},
onUnlogin: function(){
this.onError("您還沒(méi)有登錄或登錄已過(guò)期,請(qǐng)登錄",5,'')
},
onUnFound: function(){
this.onError("您要的內(nèi)容沒(méi)有找到",2,'')
}
};
this.setMethodGet = function(){
this.netMethod = 'GET';
return this;
}
this.setApiOld = function(){
this.isNewApi = false;
return this;
}
this.send = function(){
request(this);
}
}
//todo 拷貝這段代碼去用--buildRequest里的callback
/*
onPre: function(){},
onEnd: function(){
hideLoadingDialog(page);
},
onSuccess:function (data){},
onEmpty : function(){},
onError : function(msgCanShow,code,hiddenMsg){},
onUnlogin: function(){
this.onError("您還沒(méi)有登錄或登錄已過(guò)期,請(qǐng)登錄",5,'')
},
onUnFound: function(){
this.onError("您要的內(nèi)容沒(méi)有找到",2,'')
}
* */
/**
* 注意,此方法調(diào)用后還要調(diào)用.send()才是發(fā)送出去.
* @param page
* @param urlTail
* @param params
* @param callback 拷貝上方注釋區(qū)的代碼使用
* @returns {requestConfig}
*/
function buildRequest(page,urlTail,params,callback){
var config = new requestConfig();
config.page = page;
config.urlTail = urlTail;
if (getApp().globalData.session_id == null || getApp().globalData.session_id == ''){
params.session_id=''
}else {
params.session_id = getApp().globalData.session_id;
}
if (params.pageIndex == undefined || params.pageIndex <=0 || params.pageSize == 0){
params.pageSize=0
}else {
if (params.pageSize == undefined){
params.pageSize = getApp().globalData.defaultPageSize;
}
}
log(params)
config.params = params;
log(config.params)
//config.callback = callback;
if(isFunction(callback.onPre)){
config.callback.onPre=callback.onPre;
}
if(isFunction(callback.onEnd)){
config.callback.onEnd=callback.onEnd;
}
if(isFunction(callback.onEmpty)){
config.callback.onEmpty=callback.onEmpty;
}
if(isFunction(callback.onSuccess)){
config.callback.onSuccess=callback.onSuccess;
}
if(isFunction(callback.onError)){
config.callback.onError=callback.onError;
}
if(isFunction(callback.onUnlogin)){
config.callback.onUnlogin=callback.onUnlogin;
}
if(isFunction(callback.onUnFound)){
config.callback.onUnFound=callback.onUnFound;
}
return config;
}
function request(requestConfig){
//檢驗(yàn)三個(gè)公有參數(shù)并處理.這里與上面有所重復(fù),是為了兼容之前寫的幾個(gè)api,不想改了.
requestConfig.params.sessionId= getApp().globalData.sessionId;
if (requestConfig.params.sessionId ==null || requestConfig.params.sessionId == ''){
delete requestConfig.params.sessionId;
}
if (requestConfig.params.pageIndex ==0 || requestConfig.params.pageSize == 0){
delete requestConfig.params.pageIndex ;
delete requestConfig.params.pageSize;
}
//var body = getStr("&", requestConfig.params);//拼接請(qǐng)求參數(shù)
requestConfig.onPre();//請(qǐng)求發(fā)出前
wx.request({
// url: getApp().globalData.apiHeadUrl+requestConfig.urlTail+"?"+body,貌似這樣寫,同時(shí)不給data賦值,post請(qǐng)求也是可以成功的
url: getApp().globalData.apiHeadUrl+requestConfig.urlTail,
method:requestConfig.netMethod,
data:requestConfig.params,
header: {'Content-Type':'application/json'},
success: function(res) {
console.log(res);
if(res.statusCode = 200){
var responseData = res.data
var code = responseData.code;
var msg = responseData.message;
if(code == 0){
var data = responseData.data;
var isDataNull = isOptStrNull(data);
if(isDataNull){
requestConfig.onEmpty();
}else{
requestConfig.onSuccess(data);
}
}else if(code == 2){
requestConfig.onUnFound();
}else if(code == 5){
requestConfig.onUnlogin();
}else{
var isMsgNull = isOptStrNull(msg);
if(isMsgNull){
var isCodeNull = isOptStrNull(code);
if (isCodeNull){
requestConfig.onError("數(shù)據(jù)異常!,請(qǐng)核查",code,'');
}else {
requestConfig.onError("數(shù)據(jù)異常!,錯(cuò)誤碼為"+code,code,'');
}
}else{
requestConfig.onError(msg,code,'');
}
}
}else if(res.statusCode >= 500){
requestConfig.onError("服務(wù)器異常!",res.statusCode,'');
}else if(res.statusCode >= 400 && res.statusCode < 500){
requestConfig.onError("沒(méi)有找到內(nèi)容",res.statusCode,'');
}else{
requestConfig.onError("網(wǎng)絡(luò)請(qǐng)求異常!",res.statusCode,'');
}
},
fail:function(res){
console.log("fail",res)
requestConfig.onError("網(wǎng)絡(luò)請(qǐng)求異常!",res.statusCode,'');
},
complete:function(res){
// that.setData({hidden:true,toast:true});
}
})
}
方法寫在netUtil.js下,在該js文件最下方暴露方法:
module.exports = {
buildRequest:buildRequest
}
實(shí)際引用:
var netUtil=require("../../utils/netUtil.js");
小技巧: js無(wú)法像java一樣定義好了接口,然后IDE自動(dòng)生成代碼.可以這樣: 將callback的空方法寫到netUtil的buildRequest方法上方的注釋區(qū),每次用時(shí),點(diǎn)擊方法名跳到那邊去拷貝即可.
var params = {};
params.id = id;
netUtil.buildRequest(that,API.Album.DETAIL,params,{
onPre: function(){
netUtil.showLoadingDialog(that);
},
onEnd:function(){
},
onSuccess:function (data){
netUtil.showContent(that);
....
},
onEmpty : function(){
},
onError : function(msgCanShow,code,hiddenMsg){
netUtil.showErrorPage(that,msgCanShow);
},
onUnlogin: function(){
this.onError("您還沒(méi)有登錄或登錄已過(guò)期,請(qǐng)登錄",5,'')
},
onUnFound: function(){
this.onError("您要的內(nèi)容沒(méi)有找到",2,'')
}
}).send();
參考微信文檔中ui設(shè)計(jì)規(guī)范,上拉加載更多的ui提示應(yīng)該放在頁(yè)面最下部占一行,而不應(yīng)該在頁(yè)面中間顯示一個(gè)大大的loading的效果.
通過(guò)上面的分析,可以確定大部分頁(yè)面的通用狀態(tài)管理邏輯,那么就可以設(shè)計(jì)通用的狀態(tài)管理模板了.
ui的顯示是通過(guò)Page里的data中的數(shù)據(jù)來(lái)控制的,并通過(guò)page.setData({xxx})來(lái)刷新的,原先每個(gè)頁(yè)面都拷貝同樣的js屬性和wxml代碼去實(shí)現(xiàn)封裝,后來(lái)進(jìn)行了封裝,js屬性用方法來(lái)封裝,通過(guò)微信提供的template封裝共同的wxml代碼,通過(guò)import或include導(dǎo)入到wxml中(但是不知什么bug,template一直無(wú)法起作用).
function netStateBean(){
//toast的是老api,工具升級(jí)后無(wú)需設(shè)置了
this.toastHidden=true,
this.toastMsg='',
this.loadingHidden=false,
this.emptyHidden = true,
this.emptyMsg='暫時(shí)沒(méi)有內(nèi)容,去別處逛逛吧',
this.errorMsg='',
this.errorHidden=true,
this.loadmoreMsg='加載中...',
this.loadmoreHidden=true,
}
Page(
data: {
title:'名師',//todo 設(shè)置標(biāo)題欄
emptyMsg:'暫時(shí)沒(méi)有內(nèi)容,去別處逛逛吧',//todo 空白頁(yè)面的顯示內(nèi)容
netStateBean: new netUtil.netStateBean(),
...
},
...
)
<template name="pagestate" >
<view class ="empty_view" wx: