??關(guān)于微信小程序開(kāi)發(fā)一直想寫(xiě)一篇相關(guān)的文章總結(jié)和記錄下,結(jié)果拖延癥犯了遲遲沒(méi)有下筆;這不最近天氣不錯(cuò),于是找一個(gè)空閑的下午將這篇文章輸出下(好像跟天氣沒(méi)啥關(guān)系),那我們就開(kāi)始吧!
注意:本文默認(rèn)開(kāi)發(fā)者對(duì)微信小程序開(kāi)發(fā)有一定語(yǔ)法基礎(chǔ)。小程序開(kāi)發(fā)文檔
相關(guān)免費(fèi)學(xué)習(xí)推薦:微信小程序開(kāi)發(fā)
微信小程序小結(jié)
??在接觸的微信小程序開(kāi)發(fā)過(guò)程中,不難發(fā)現(xiàn)微信小程序?yàn)榱朔奖汩_(kāi)發(fā)人員入手對(duì)很多底層api進(jìn)行了很好的封裝,比如針對(duì)接口請(qǐng)求的wx.request()
,針對(duì)路由跳轉(zhuǎn)和頁(yè)面導(dǎo)航的wx.switchTab、wx.navigateTo···
等。雖然在一定程度上簡(jiǎn)化了開(kāi)發(fā),但是對(duì)于項(xiàng)目工程的系統(tǒng)化構(gòu)建還是不夠的,因此本人在對(duì)比以前基于Vue開(kāi)發(fā)項(xiàng)目的經(jīng)驗(yàn)和自身的開(kāi)發(fā)習(xí)慣,總結(jié)出如下3點(diǎn)可供參考:
1、全局變量和配置信息統(tǒng)一管理;
2、封裝路由守衛(wèi)相關(guān)api:
vue-router
的router.beforeEach()
和router.afterEach()
真的香;3、接口請(qǐng)求公共信息進(jìn)一步提取封裝;
4、封裝接口的請(qǐng)求和響應(yīng)攔截api:
axios
的axios.interceptors.request.use()
和axios.interceptors.response.use()
用過(guò)的都說(shuō)好;
從上述四點(diǎn)出發(fā),對(duì)微信小程序初始化工程進(jìn)行規(guī)范優(yōu)化,能夠很大程度提高開(kāi)發(fā)效率和進(jìn)行項(xiàng)目維護(hù)管理。封裝的好處不只體現(xiàn)在調(diào)用的方便上,也體現(xiàn)在管理的方便上,同時(shí),公共操作集中處理,很大程度減少繁雜重復(fù)代碼。
一、項(xiàng)目初始化
???新建微信小程序項(xiàng)目,在項(xiàng)目下新建如下目錄和文件:
- config文件夾:統(tǒng)一管理可配置的信息和變量;
- erroList.js:接口報(bào)錯(cuò)
錯(cuò)誤碼
匹配列表文件; - globalData.js:
全局變量
統(tǒng)一管理文件(相當(dāng)于vuex); - keys.js:可配置系統(tǒng)信息管理文件(全局常量命名等);
- erroList.js:接口報(bào)錯(cuò)
- pages文件夾:小程序頁(yè)面文件管理文件夾(每個(gè)頁(yè)面一個(gè)子文件夾目錄);
- router文件夾:路由管理文件件;
- router.js:對(duì)微信小程序
5種路由導(dǎo)航
api的封裝; - routerConfig.js:頁(yè)面路由名稱(chēng)和路徑匹配配置文件;
- routerFilter.js:路由前置
攔截
封裝;
- router.js:對(duì)微信小程序
- servers文件件:接口請(qǐng)求服務(wù)管理文件夾;
- apis文件夾:request請(qǐng)求封裝管理和接口api配置管理文件夾;
- request.js:對(duì)
wx.request
的Promise
封裝; - xxx.js:對(duì)應(yīng)模塊的接口管理文件;
- request.js:對(duì)
- requestFilter.js:接口
請(qǐng)求和響應(yīng)攔截
封裝文件;
- apis文件夾:request請(qǐng)求封裝管理和接口api配置管理文件夾;
- 其他都是初始化默認(rèn)文件;
二、路由跳轉(zhuǎn)和路由守衛(wèi)封裝
1、路由跳轉(zhuǎn)封裝
??微信小程序官方文檔為開(kāi)發(fā)者提供了5種路由跳轉(zhuǎn)的api,每一種都有其特殊的用法:
??根據(jù)其用法,我們對(duì)路由api進(jìn)行如下封裝:微信小程序路由跳轉(zhuǎn)最后對(duì)應(yīng)push、replace、pop、relaunch、switchTab
;routes
對(duì)應(yīng)routeConfig.js中路由路徑的配置;routerFilter
對(duì)應(yīng)routerFilter.js文件,對(duì)路由跳轉(zhuǎn)之前的邏輯進(jìn)行處理;
routeConfig.js(每次新增頁(yè)面后需要手動(dòng)添加):
export?const?routes?=? ??{ ????INDEX:?"/pages/index/index", ????TEST:?"/pages/test/test", ??}export?default?{...routes};
routerFilter.js:
export?default?()?=>?{ ??···??//路由跳轉(zhuǎn)前邏輯處理}
router.js(routerFilter負(fù)責(zé)路由跳轉(zhuǎn)前公共操作處理,在success和fail中對(duì)路由跳轉(zhuǎn)后的公共操作進(jìn)行處理):
import?routes?from?"../router/routerConfig";import?routerFilter?from?"./routerFilter"/** ?*?對(duì)wx.navigateTo的封裝 ?*?@param?{路由}?path? ?*?@param?{參數(shù)}?params? ?*?@param?{事件}?events? ?*/const?push?=?(path,?params,?events)?=>?{ ??routerFilter() ??wx.navigateTo({ ????url:?routes[path]?+?`?query=${JSON.stringify(params)}`, ????events:?events, ????success(res)?{ ??????console.log(res); ????}, ????fail(err)?{ ??????console.log(err); ????} ??})}/** ?*?對(duì)wx.redirectTo的封裝 ?*?@param?{路由}?path? ?*?@param?{參數(shù)}?params? ?*/const?replace?=?(path,?params)?=>?{ ??routerFilter() ??wx.redirectTo({ ????url:?routes[path]?+?`?query=${JSON.stringify(params)}`, ????success(res)?{ ??????console.log(res); ????}, ????fail(err)?{ ??????console.log(err); ????} ??})}/** ?*?對(duì)wx.navigateBack的封裝 ?*?@param?{返回的層級(jí)}?number? ?*/const?pop?=?(number)?=>?{ ??routerFilter() ??wx.navigateBack({ ????delta:?number, ????success(res)?{ ??????console.log(res); ????}, ????fail(err)?{ ??????console.log(err); ????} ??})}/** ?*?對(duì)wx.reLaunch的封裝 ?*?@param?{路由}?path? ?*?@param?{參數(shù)}?params? ?*/const?relaunch?=?(path,?params)?=>?{ ??routerFilter() ??wx.reLaunch({ ????url:?routes[path]?+?`?query=${JSON.stringify(params)}`, ????success(res)?{ ??????console.log(res); ????}, ????fail(err)?{ ??????console.log(err); ????} ??})}/** ?*?對(duì)tabbar的封裝 ?*?@param?{路由}?path? ?*/const?switchTab?=?(path)?=>?{ ??routerFilter() ??wx.switchTab({ ????url:?routes[path], ????success(res)?{ ??????console.log(res); ????}, ????fail(err)?{ ??????console.log(err); ????} ??})}module.exports?=?{ ??push, ??replace, ??pop, ??relaunch, ??switchTab}
2、全局注冊(cè)和使用
在app.js
中對(duì)封裝的路由api進(jìn)行全局注冊(cè):
import?router??from?"./router/router.js"//全局注冊(cè)wx.router?=?router
在頁(yè)面邏輯中使用:
//index頁(yè)面跳轉(zhuǎn)test頁(yè)面?gotoTest(){ ???wx.router.push("TEST")}
三、接口請(qǐng)求Promise封裝
??對(duì)于同一個(gè)項(xiàng)目而言,微信小程序apiwx.request()
中很多參數(shù)都是相同的,如果直接使用,需要將這些重復(fù)參數(shù)一遍又一遍的copy,雖然copy很簡(jiǎn)單,但是當(dāng)有一個(gè)參數(shù)改變了需要找到所有接口一個(gè)一個(gè)修改,維護(hù)起來(lái)費(fèi)勁,再者看著也難受呀;
??借鑒axios
對(duì)請(qǐng)求的封裝,將wx.request()
封裝為Promise
形式豈不美哉:
request.js:
import?formatError?from?"../requestFilter"const?app?=?getApp()/** ?*?接口請(qǐng)求封裝 ?*?@param?{請(qǐng)求方式}?method? ?*?@param?{請(qǐng)求的url}?url? ?*?@param?{請(qǐng)求傳遞的數(shù)據(jù)}?data? ?*/const?request?=?(method,?url,?data)?=>?{ ??//設(shè)置請(qǐng)求頭 ??const?header?=?{ ????···??} ??//promise封裝一層,使得調(diào)用的時(shí)候直接用then和catch接收 ??return?new?Promise((resolve,?reject)?=>?{ ????wx.request({ ??????method:?method, ??????url:?app.globalData.host?+?url,?//完整的host ??????data:?data, ??????header:?header, ??????success(res)?{ ????????//對(duì)成功返回的請(qǐng)求進(jìn)行數(shù)據(jù)管理和統(tǒng)一邏輯操作 ????????···????????resolve(res.data) ??????}, ??????fail(err)?{ ????????wx.showToast({ ??????????title:?'網(wǎng)絡(luò)異常,稍后再試!', ??????????mask:?true, ??????????icon:?'none', ??????????duration:?3000 ????????}) ??????} ????}) ??})}export?default?request;
具體使用
以u(píng)ser.js為例:
import?request?from?"./request";//?獲取用戶(hù)openidexport?const?usrInfos?=?data?=>?request("POST",?"/user/usrInfos",?data);
index頁(yè)面調(diào)用:
//index.js//獲取應(yīng)用實(shí)例const?app?=?getApp()import?{?usrInfos?}?from?"../../servers/apis/user"Page({ ??onLoad:?function?()?{ ????//獲取用戶(hù)信息 ????usrInfos({ ??????uid:?"xxxx" ????}) ??????.then(res?=>?{ ????????console.log(res) ??????}) ??????.catch(err?=>?{ ????????console.log(err) ??????}) ??}})
四、接口的請(qǐng)求和響應(yīng)攔截封裝
??axios
的axios.interceptors.request.use()
和axios.interceptors.response.use()
分別對(duì)應(yīng)接口請(qǐng)求前的攔截處理和數(shù)據(jù)響應(yīng)后的攔截處理;根據(jù)這個(gè)原理我們對(duì)微信小程序的響應(yīng)也做攔截封裝,對(duì)接口請(qǐng)求返回錯(cuò)誤進(jìn)行統(tǒng)一管理輸出:
request.js
import?formatError?from?"../requestFilter"const?app?=?getApp()···const?request?=?(method,?url,?data)?=>?{ ??···??return?new?Promise((resolve,?reject)?=>?{ ????wx.request({ ??????···??????success(res)?{ ????????//對(duì)成功返回的請(qǐng)求進(jìn)行數(shù)據(jù)管理和統(tǒng)一邏輯操作 ????????if(res.statusCode?===?200){?//請(qǐng)求返回成功 ??????????if(res.data?&&?res.data.code?===?"SUCCESS"){?//后端對(duì)接口請(qǐng)求處理成功,返回?cái)?shù)據(jù)給接口調(diào)用處 ????????????resolve(res.data)??//then接收 ??????????}else{ //后端對(duì)也請(qǐng)求判斷后認(rèn)為不合邏輯報(bào)錯(cuò) ????????????formatError(res)???//統(tǒng)一的報(bào)錯(cuò)處理邏輯 ????????????reject(res.data)? //catch接收 ??????????}? ????????}else{ ??????????reject(res.data) //catch接收 ????????} ??????}, ??????fail(err)?{ //請(qǐng)求不通報(bào)錯(cuò) ????????wx.showToast({ ??????????title:?'網(wǎng)絡(luò)異常,稍后再試!', ??????????mask:?true, ??????????icon:?'none', ??????????duration:?3000 ????????}) ??????} ????}) ??})}export?default?request;
requestFilter.js
requestFilter.js中可以做很多對(duì)報(bào)錯(cuò)的處理,這里用一個(gè)簡(jiǎn)單的toast處理示范下:
/** ?*?對(duì)接口返回的后端錯(cuò)誤進(jìn)行格式轉(zhuǎn)化 ?*?@param?{接口成功返回的數(shù)據(jù)}?res? ?*/const?formatError?=?(err?=>{ ??wx.showToast({ ????title:?err.message, ????mask:?false, ????icon:?'none', ????duration:?3000 ??})}export?default?formatError;
對(duì)報(bào)錯(cuò)進(jìn)行統(tǒng)一處理需要明確數(shù)據(jù)規(guī):
- 制定統(tǒng)一的報(bào)錯(cuò)碼管理規(guī)范;
- 制定前后端統(tǒng)一的接口請(qǐng)求數(shù)據(jù)返回格式;
五、全局?jǐn)?shù)據(jù)管理
??對(duì)于數(shù)據(jù)的管理在小項(xiàng)目的開(kāi)發(fā)中顯得不那么重要,但是隨著項(xiàng)目越來(lái)越大,數(shù)據(jù)越來(lái)越多,一個(gè)很好的數(shù)據(jù)管理方案能夠有效地避免很多bug,這也是vuex能夠在vue生態(tài)中占有一席之地的原因。秉承著合理管理數(shù)據(jù)的原則,對(duì)于該封裝的數(shù)據(jù)堅(jiān)決封裝,對(duì)于該分模塊管理的配置堅(jiān)決分塊管理:
globalData.js
微信小程序中全局的數(shù)據(jù)管理放在app.js
的globalData
屬性中,當(dāng)數(shù)據(jù)太多或者app.js邏輯太復(fù)雜時(shí),將全局?jǐn)?shù)據(jù)提取出來(lái)單獨(dú)管理的確是個(gè)好方案:
export?default?{ ??··· ??host:?"http://www.wawow.xyz/api/test",?//接口請(qǐng)求的域名和接口前綴? ??hasConfirm:?""?//是否已經(jīng)有了confirm實(shí)例 ??currentPage:?"" ??···}
keys.js
keys.js屬于個(gè)人開(kāi)發(fā)中的習(xí)慣操作,將項(xiàng)目中可能用到的一些常量名稱(chēng)在此集中管理起來(lái),十分方便調(diào)用和修改維護(hù):
export?default?{ ??···??TOKEN:?"token", ??STORAGEITEM:?"test" ??···}
全局引用和注冊(cè)
引入app.js:
import?router??from?"./router/router.js"import?keys?from?"./config/keys"import?globalData?from?"./config/globalData"//全局注冊(cè)wx.router?=?router wx.$KEYS?=?keys//app.jsApp({ ??//監(jiān)聽(tīng)小程序初始化 ??onLaunch(options)?{ ????//獲取小程序初始進(jìn)入的頁(yè)面信息 ????let?launchInfos?=?wx.getLaunchOptionsSync() ????//將當(dāng)前頁(yè)面路由存入全局的數(shù)據(jù)管理中 ????this.globalData.currentPage?=?launchInfos.path??}, ??···??//全局?jǐn)?shù)據(jù)存儲(chǔ) ??globalData:?globalData})
使用
在頁(yè)面代碼邏輯中可以通過(guò)app.globalData.host
,wx.$KEYS.TOKEN
方式進(jìn)行調(diào)用;
六、總結(jié)
??上述關(guān)于微信小程序開(kāi)發(fā)的幾個(gè)方面都是在實(shí)踐中學(xué)習(xí)和總結(jié)的,技術(shù)層面的實(shí)現(xiàn)其實(shí)很容易,但是個(gè)人覺(jué)得開(kāi)發(fā)規(guī)范項(xiàng)目工程構(gòu)建才是一個(gè)項(xiàng)目的重要基礎(chǔ);完善的規(guī)范能夠有效的提高開(kāi)發(fā)效率和開(kāi)發(fā)者之間非必要的扯皮
!合理的項(xiàng)目工程構(gòu)建能夠優(yōu)化開(kāi)發(fā)邏輯,提高代碼邏輯易讀性,減少后期項(xiàng)目的管理時(shí)間,同時(shí)給予項(xiàng)目更大的擴(kuò)展性。
??有需要源碼的可以關(guān)注微信公眾號(hào) 哇喔WEB 回復(fù) "wxmp"獲??;
??歡迎大家討論留言、進(jìn)行補(bǔ)充!
相關(guān)學(xué)習(xí)推薦:小程序開(kāi)發(fā)教程
以上是讓微信小程序開(kāi)發(fā)如魚(yú)得水的方法的詳細(xì)內(nèi)容。更多信息請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線(xiàn)人工智能工具。

Clothoff.io
AI脫衣機(jī)

Video Face Swap
使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱門(mén)文章

熱工具

記事本++7.3.1
好用且免費(fèi)的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強(qiáng)大的PHP集成開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)代碼編輯軟件(SublimeText3)