微信提供的開發工具的編輯功能不是一般的水,寫代碼肯定不能用它,否則就是浪費生命.不說別的,連自動保存都沒有,第一次寫時寫了一個多小時,后面下班直接關掉,也不彈出提示說沒保存.然后第二天過來,寫的代碼全沒了!!! 頓時感到巨坑無比.這些工具開發人員吃干飯的么???
(后來的版本已經修復不能自動保存的問題了,當然編輯功能還是不好用.)
它的正確用法是作為運行和調試工具.
那么適合作為編輯工具的是: webStorm.基于IntelJ內核,開啟Dracula主題,跟Android studio的使用習慣非常接近,so cool!各種方法提示,自動保存,快速查找...應有盡有.閉源的微信開發工具就不要用來寫代碼了,珍惜生命.
webStorm要識別wxml和wxss,還需要配置一下文件類型:(看下面別人截的圖)
記住html和css里都要加上微信小程序對應的類型
綜上,開發時,用webstorm來寫代碼,用微信開發工具來運行和調試,速度颼颼的!
微信提供了底層網絡驅動以及成功和失敗的回調.但對于一個項目中的實際使用而言,仍然還是顯得繁瑣,還有很多封裝和簡化的空間.
wx.request({ url: 'test.php',//請求的url data: {//請求的參數 x: '' , y: '' }, header: {//請求頭 'Content-Type': 'application/json' }, method:"POST", success: function(res) {//成功的回調 console.log(res.data) } })
對于一個網絡訪問來說,請求一般是get和post,拼上各種參數以及請求頭,然后拿到回來的響應,解析并得到最終需要的數據.
對于具體項目來說,請求時會有每個(或大多數)請求都要帶的參數,都要帶的請求頭,返回的數據格式可能都是一致的,那么基于此,對微信的網絡請求api進行二次封裝:
在我目前的項目中,
大多數請求是post,基本上每個請求都需要攜帶sessionId來與服務器驗證登錄狀態,還有很多請求是基于分頁的,需要帶上pageSize和pageIndex.
再跟頁面邏輯關聯起來,請求可能是因為第一次進入頁面,或者刷新,或者上拉加載更多.
大多數拿到的數據格式是標準json格式,如下
{ "code":1, "data":xxx,//可能是String,也可能是JsonObject,或JsonArray,也可能是null,或undefined "msg":yyy//可能為空 }
通過請求的狀態碼code來判斷這個請求是否真正成功.我們的項目中還有常見的是code=5:登錄過期或未登錄,code=2: 沒有找到對應的內容 等等.
如果是大多數情況的請求時,只需要指定:
對于響應,我們只需要:
我們期望的api是:
netUtil.buildRequest(page,urlTail,params,callback)//必須的參數和回調 .setXxx(xxx)//額外的設置,鏈式調用 .. .send();//最終發出請求的動作
//這兩個錯誤碼是項目接口文檔統一定義好的 const code_unlogin = 5; const code_unfound = 2; function requestConfig(){ this.page; //頁面對象 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("您還沒有登錄或登錄已過期,請登錄",5,'') }, onUnFound: function(){ this.onError("您要的內容沒有找到",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("您還沒有登錄或登錄已過期,請登錄",5,'') }, onUnFound: function(){ this.onError("您要的內容沒有找到",2,'') } * */ /** * 注意,此方法調用后還要調用.send()才是發送出去. * @param page * @param urlTail * @param params * @param callback 拷貝上方注釋區的代碼使用 * @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){ //檢驗三個公有參數并處理.這里與上面有所重復,是為了兼容之前寫的幾個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);//拼接請求參數 requestConfig.onPre();//請求發出前 wx.request({ // url: getApp().globalData.apiHeadUrl+requestConfig.urlTail+"?"+body,貌似這樣寫,同時不給data賦值,post請求也是可以成功的 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("數據異常!,請核查",code,''); }else { requestConfig.onError("數據異常!,錯誤碼為"+code,code,''); } }else{ requestConfig.onError(msg,code,''); } } }else if(res.statusCode >= 500){ requestConfig.onError("服務器異常!",res.statusCode,''); }else if(res.statusCode >= 400 && res.statusCode < 500){ requestConfig.onError("沒有找到內容",res.statusCode,''); }else{ requestConfig.onError("網絡請求異常!",res.statusCode,''); } }, fail:function(res){ console.log("fail",res) requestConfig.onError("網絡請求異常!",res.statusCode,''); }, complete:function(res){ // that.setData({hidden:true,toast:true}); } }) }
方法寫在netUtil.js下,在該js文件最下方暴露方法:
module.exports = { buildRequest:buildRequest }
實際引用:
var netUtil=require("../../utils/netUtil.js");
小技巧: js無法像java一樣定義好了接口,然后IDE自動生成代碼.可以這樣: 將callback的空方法寫到netUtil的buildRequest方法上方的注釋區,每次用時,點擊方法名跳到那邊去拷貝即可.
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("您還沒有登錄或登錄已過期,請登錄",5,'') }, onUnFound: function(){ this.onError("您要的內容沒有找到",2,'') } }).send();
參考微信文檔中ui設計規范,上拉加載更多的ui提示應該放在頁面最下部占一行,而不應該在頁面中間顯示一個大大的loading的效果.
通過上面的分析,可以確定大部分頁面的通用狀態管理邏輯,那么就可以設計通用的狀態管理模板了.
ui的顯示是通過Page里的data中的數據來控制的,并通過page.setData({xxx})來刷新的,原先每個頁面都拷貝同樣的js屬性和wxml代碼去實現封裝,后來進行了封裝,js屬性用方法來封裝,通過微信提供的template封裝共同的wxml代碼,通過import或include導入到wxml中(但是不知什么bug,template一直無法起作用).
function netStateBean(){ //toast的是老api,工具升級后無需設置了 this.toastHidden=true, this.toastMsg='', this.loadingHidden=false, this.emptyHidden = true, this.emptyMsg='暫時沒有內容,去別處逛逛吧', this.errorMsg='', this.errorHidden=true, this.loadmoreMsg='加載中...', this.loadmoreHidden=true, }
Page( data: { title:'名師',//todo 設置標題欄 emptyMsg:'暫時沒有內容,去別處逛逛吧',//todo 空白頁面的顯示內容 netStateBean: new netUtil.netStateBean(), ... }, ... )
<template name="pagestate" > <view class ="empty_view" wx: