uni-app開發(fā)多端應(yīng)用踩坑:搭建uni-app項目架構(gòu)

大家好,我是前端dog君,一名95后前端小兵。2019年畢業(yè)于北京化工大學(xué),天津人,不知道有校友和老鄉(xiāng)嘛?對前端的熱愛,讓我們在此相聚,希望這篇文章,能幫助到您,也同時希望能交到志同道合的小伙伴,共同發(fā)展,一起進(jìn)步。我的微信號dm120225,備注簡書,期待您的光臨。

最近這段時間,應(yīng)公司需求,需要開發(fā)一款A(yù)pp,但是公司只有前端團隊,可能大家一致認(rèn)為,只要是關(guān)于GUI的開發(fā)前端都可以搞定吧,于是,dog君就接下了App的活兒,開始了App探索之旅。
在做技術(shù)選型的過程中,dog君調(diào)研了幾種混合App開發(fā)方案,像mui、Ionic、React-native、cordova、uni-app、Flutter等等,從團隊技術(shù)棧和上手速度的角度來說,我們最終選用了uni-app,vue的語法,小程序的API,來開發(fā)一款A(yù)pp應(yīng)用。下面跟隨dog君的腳步,讓我們一起來體驗uni-app開發(fā)跨端應(yīng)用。

如何學(xué)習(xí)新技術(shù)

在我們的前端圈,新技術(shù)層出不窮,每天都會有新輪子的產(chǎn)生,那么在開始之前呢,先來談下當(dāng)我們需要使用一種沒接觸過的技術(shù)進(jìn)行日常開發(fā)工作時,我們應(yīng)該如何來學(xué)習(xí),dog君是這樣做的:

  • 找一個關(guān)于uni-app開發(fā)的視頻開始學(xué)習(xí),大概搞清楚如何使用及流程是什么樣的。
  • github上找一個比較好的uni-app開發(fā)的項目,學(xué)習(xí)一下他們是如何開發(fā)的,同時不斷的查閱,實踐,掃盲,踩坑。
  • 開始搭建uni-app 項目架構(gòu),盡量不脫離現(xiàn)有的開發(fā)習(xí)慣,降低學(xué)習(xí)成本。學(xué)習(xí)他人的項目架構(gòu),靠近社區(qū),使用現(xiàn)有的解決方案。
  • 搭建完畢后,根據(jù)需求開發(fā)出一款應(yīng)用,團隊之間互相磨合。
  • 項目完畢后,整理總結(jié),輸出一份文檔,方便其他同事維護(hù)。

什么是uni-app

uni-app 是一個使用 Vue.js 開發(fā)所有前端應(yīng)用的框架,開發(fā)者編寫一套代碼,可發(fā)布到iOS、Android、Web(響應(yīng)式)、以及各種小程序(微信/支付寶/百度/頭條/QQ/釘釘/淘寶)、快應(yīng)用等多個平臺。

搭建開發(fā)環(huán)境

uni-app是DCloud公司產(chǎn)品,DCloud公司為我們提供了HBuilder X集成開發(fā)環(huán)境,開箱即用,無需配置nodejs。
我們首先下載HBuilder X

HBuilderX是通用的前端開發(fā)工具,但為uni-app做了特別強化。

HBuilder X下載界面

下載App開發(fā)版,可開箱即用;如下載標(biāo)準(zhǔn)版,在運行或發(fā)行uni-app時,會提示安裝uni-app插件,插件下載完成后方可使用。這里我們選擇App開發(fā)版。

下載完畢后,我們打開打開HBuilder X,出現(xiàn)以下頁面


HBuilder X界面

好,到這里你會驚奇的發(fā)現(xiàn),我們的開發(fā)環(huán)境已經(jīng)搭建完畢。

這里呢需要提醒大家一點,在dog君使用過程中呢,發(fā)現(xiàn)第一次下載后的HBuilder X存在打不開的問題,當(dāng)然,小伙伴們遇到的情況也各不相同,如果遇到一些奇奇怪怪的問題,我們重新啟動下電腦,或者重新啟動下HBuilder X,所有的問題就都迎刃而解了。

創(chuàng)建uni-app項目

我們點擊工具欄的文件 -> 新建 -> 項目


選擇uni-app類型,輸入工程名,選擇模板,點擊創(chuàng)建,即可成功創(chuàng)建。


uni-app自帶的模板有 Hello uni-app ,是官方的組件和API示例。還有一個重要模板是 uni ui項目模板,日常開發(fā)推薦使用該模板,已內(nèi)置大量常用組件。

此時,我們的uni-app 項目已經(jīng)創(chuàng)建完畢。

運行uni-app

我們的uni-app強大之處,在于一套代碼,多端運行,目前已支持Android、IOS、Web、微信小程序、支付寶、百度、字節(jié)跳動、QQ、360小程序和快應(yīng)用。這里呢,我們討論下運行到安卓、Web和微信小程序的步驟。

1.運行到瀏覽器
選擇我們剛才創(chuàng)建的項目,點擊工具欄的運行 -> 運行到瀏覽器 -> 選擇瀏覽器,即可在瀏覽器里面體驗uni-app 的 H5 版。


2.運行到安卓手機
選擇我們剛才創(chuàng)建的項目,連接手機,開啟USB調(diào)試,進(jìn)入hello-uniapp項目,點擊工具欄的運行 -> 真機運行 -> 選擇運行的設(shè)備,即可在該設(shè)備里面體驗uni-app。

這里dog君總結(jié)下我們可能遇到的問題及解決方案:
1.如何開啟手機USB調(diào)試?
開啟手機usb調(diào)試模式
2.開啟后并連接手機,但是HBuilder X并沒有反應(yīng)?
點擊工具欄運行,找到運行到手機或模擬器,反復(fù)的觸摸,直到顯示連接為止。實在不行,重啟HBuilder X或電腦。
如手機無法識別,請點擊菜單運行-運行到手機或模擬器-真機運行常見故障排查指南。 注意目前開發(fā)App也需要安裝微信開發(fā)者工具。

3.運行到微信開發(fā)者工具
選擇我們剛才創(chuàng)建的項目,點擊工具欄的運行 -> 運行到小程序模擬器 -> 微信開發(fā)者工具,即可在微信開發(fā)者工具里面體驗uni-app。

這里有一些需要注意的點:
如果是第一次使用,需要先配置微信開發(fā)者工具的相關(guān)路徑,才能運行成功。如下圖,點擊工具欄的運行-> 運行到小程序模擬器 -> 運行設(shè)置,找到微信開發(fā)者工具路徑。 若HBuilderX不能正常啟動微信開發(fā)者工具,需要開發(fā)者手動啟動,然后將uni-app生成小程序工程的路徑拷貝到微信開發(fā)者工具里面,在HBuilderX里面開發(fā),在微信開發(fā)者工具里面就可看到實時的效果。

好,到此為止呢,我們已經(jīng)成功的將項目運行在多個平臺了。

發(fā)布uni-app

打包為遠(yuǎn)程App(云端)

在HBuilderX工具欄,點擊發(fā)行,選擇原生app-云端打包,如下圖:


配置相關(guān)項,點擊打包即可。

發(fā)布為H5

1.在 manifest.json 的可視化界面,進(jìn)行如下配置(發(fā)行在網(wǎng)站根目錄可不配置應(yīng)用基本路徑),此時發(fā)行網(wǎng)站路徑是 www.xxx.com/h5,如:https://hellouniapp.dcloud.net.cn。


2.在HBuilderX工具欄,點擊發(fā)行,選擇網(wǎng)站-H5手機版,如下圖,點擊即可生成 H5 的相關(guān)資源文件,保存于 unpackage 目錄。

發(fā)布為微信小程序

1.申請微信小程序AppID
2.在HBuilderX中頂部菜單依次點擊 "發(fā)行" => "小程序-微信",輸入小程序名稱和appid點擊發(fā)行即可在 unpackage/dist/build/mp-weixin 生成微信小程序項目代碼。



3.在微信小程序開發(fā)者工具中,導(dǎo)入生成的微信小程序項目,測試項目代碼運行正常后,點擊“上傳”按鈕,之后按照 “提交審核” => “發(fā)布” 小程序標(biāo)準(zhǔn)流程,逐步操作即可

到此為止,我們的uni-app項目初體驗已經(jīng)完畢。

uni-app開發(fā)注意事項

uni-app 是一款使用vue的語法,小程序的api開發(fā)多端應(yīng)用的框架,uni-app本身并不難,難得是我們在開發(fā)多端應(yīng)用的過程中需要遵循各端的規(guī)則,這不是uni-app在技術(shù)層面可以抹平的:

  • 比如H5端的瀏覽器有跨域限制;
  • 比如微信小程序會強制要求https鏈接,并且所有要聯(lián)網(wǎng)的服務(wù)器域名都要配到微信的白名單中;
  • 比如App端,iOS對隱私控制和虛擬支付控制非常嚴(yán)格;
  • 比如App端,Android、國產(chǎn)rom各種兼容性差異,尤其是因為谷歌服務(wù)被墻,導(dǎo)致的push、定位等開發(fā)混亂的坑;
  • 如果你的App要使用三方sdk,比如定位、地圖、支付、推送...還要遵循他們的規(guī)則和限制;

dog君在使用uni-app開發(fā)App的過程中踩了很多坑,在這里分享給大家:

  • 開發(fā)規(guī)范:使用vue單文件規(guī)范,組件化和接口能力靠近小程序規(guī)范
  • 使用flex布局開發(fā)
  • 不要在static目錄下寫less scss 和js,該目錄下HBuilder并不會打包,有需要,最好放在common目錄下。
  • @指向的是項目根目錄
  • 運行環(huán)境通過process.env.NODE_ENV來判斷,默認(rèn)存在開發(fā)環(huán)境和生產(chǎn)環(huán)境,當(dāng)然,也可以自定義配置測試環(huán)境。
  • uni-app的尺寸單位有px rpx rpx為響應(yīng)式單位,750rpx為屏幕寬度,我們再和設(shè)計師交流過程中,跟設(shè)計師說明下視覺稿使用的是iPhone 6設(shè)計稿作為標(biāo)準(zhǔn)(很重要)。
  • uni-app中css不能使用 * page元素即為body
  • uni-app中導(dǎo)航欄和底部選項卡高度不可修改
  • 在css中使用背景圖片,引用路徑推薦使用~@/static/logo.png
  • uni-app的vue頁面在Android低端機上只有css瀏覽器兼容問題,因為vue頁面仍然渲染在webview中
  • uni-app支持使用npm,但是為多端考慮,建議優(yōu)先從uni-app插件市場獲取插件使用。
  • 各端的特性,我們使用條件編譯來滿足各端規(guī)則。

搭建項目架構(gòu)

dog君開發(fā)的是App,個人認(rèn)為App的規(guī)則還是比較多的,基本上覆蓋掉了小程序和H5。那么我們就以開發(fā)一個App為例,搭建uni-app項目架構(gòu),一起來看看開發(fā)一款完整App應(yīng)用,都需要有什么。

我們先來梳理一下打開一款A(yù)pp,它的運行流程和界面展示大概是什么樣子的,會涉及到什么。
1.首先,掃碼下載App到手機(非上架應(yīng)用,用戶通常會使用微信來掃描,進(jìn)入H5頁面,作用是引導(dǎo)用戶點擊右上角,從瀏覽器中打開)
2.用戶打開瀏覽器,下載App
3.下載完畢后,打開安裝包,彈出安裝App界面,安裝App到手機上。
4.安裝完成,手機上會出現(xiàn)該應(yīng)用(應(yīng)用圖標(biāo),應(yīng)用名稱
5.打開App,首次打開會彈出服務(wù)協(xié)議(服務(wù)協(xié)議配置
6.看到App啟動圖(安卓使用的是.9.png格式啟動圖
7.首次打開,進(jìn)入App引導(dǎo)頁檢查應(yīng)用是否存在更新
8.打開App,檢查用戶是否登錄,已登錄,進(jìn)入首頁,未登錄,進(jìn)入登錄頁(這里我們以未登錄為例)
9.進(jìn)入登錄頁,輸入賬號密碼,點擊登錄,進(jìn)入首頁(vuex存儲用戶信息,請求封裝,全局錯誤異常處理,各種工具函數(shù)
10.進(jìn)入首頁,查看頁面展示(導(dǎo)航欄配置,底部選項卡配置
11.進(jìn)入列表頁(下拉刷新,上拉加載,全局loading,暫無數(shù)據(jù)組件,返回頂部組件,檢查網(wǎng)絡(luò)是否連接組件,icon組件
12.旋轉(zhuǎn)手機,應(yīng)用仍豎屏顯示(配置豎屏鎖定
13.點擊列表頁,進(jìn)入詳情頁(UI庫,表單校驗,圖表庫

好,到此為止,我們梳理下搭建一個uni-app項目架構(gòu)需要什么。

  • 掃碼進(jìn)入App下載的H5頁面
  • 應(yīng)用圖標(biāo),應(yīng)用名稱
  • 服務(wù)協(xié)議配置
  • 安卓App .9.png格式啟動圖制作
  • App引導(dǎo)頁
  • app更新機制
  • uni-app使用npm包,構(gòu)建vuex moment等常用js庫
  • uni-app全局配置 導(dǎo)航欄、底部選項卡等
  • 請求封裝,環(huán)境配置,http狀態(tài)碼及自定義狀態(tài)碼,restful風(fēng)格接口規(guī)范及格式,請求超時處理,請求異常錯誤處理
  • 工具函數(shù)封裝
  • 上拉刷新、下拉加載,全局loading,暫無數(shù)據(jù)組件,返回頂部組件,檢查網(wǎng)絡(luò)連接組件,uni-app集成iconfont,配置組件自動引入。
  • 配置豎屏鎖定
  • 常用UI庫,圖表庫,表單校驗等相關(guān)uni-app插件。

好,下面我們就來針對以上需要解決的問題,一個一個的給出解決方案,最終搭建起我們的uni-app項目架構(gòu)。

掃碼進(jìn)入下載App的H5頁面

這個在此不詳細(xì)展開,因為不同公司對于推廣方式是不一樣的,我們新建一個html文件,可以使用以下代碼來判斷是否在微信瀏覽器打開,如果是,隱藏下載按鈕,同時展示一層mask蒙版,提示用戶點擊右上角從瀏覽器打開,即可,進(jìn)入瀏覽器,判斷不是在微信瀏覽器打開,下載按鈕展示出來,點擊下載按鈕,手機瀏覽器開始下載apk安裝包。

function is_weixn(){  
        var ua = navigator.userAgent.toLowerCase();  
        if(ua.match(/MicroMessenger/i)=="micromessenger") {  
            return true;  
        } else {  
            return false;  
        }  
    }
應(yīng)用圖標(biāo),應(yīng)用名稱

uni-app配置應(yīng)用圖標(biāo)有一定的要求,我們可以在創(chuàng)建的項目中找到mainfest.json文件,點擊App圖標(biāo)配置,如圖所示



和設(shè)計師溝通好,設(shè)計1024*1024尺寸的png格式圖片即可,可以自動生成圖標(biāo)。
關(guān)于應(yīng)用名稱,與產(chǎn)品經(jīng)理溝通完畢后點擊基礎(chǔ)配置,填寫應(yīng)用名稱即可,如圖所示。


安卓App.9.png制作

我們的啟動圖通常是一張圖片,為避免在不同尺寸不同分辨率下的手機導(dǎo)致啟動圖拉伸或壓縮導(dǎo)致變形,安卓平臺出現(xiàn)了可以適配各種尺寸的一種圖片格式“.9.png”。這是一種特殊的圖片格式,它可以指定特定的區(qū)域進(jìn)行拉伸而不失真。
關(guān)于.9.png圖片的制作,我們可以參考下面這篇文章
Android Studio制作.9.png圖片

從下面開始呢,我們首先使用HBuilder X創(chuàng)建一個uni-app項目,使用默認(rèn)模板,清空文件內(nèi)容,保持一個空架子的狀態(tài),我們開始基于此項目搭建uni-app項目架構(gòu)。

首先我們來看下項目目錄結(jié)構(gòu)

 ── App.vue    根組件
├── README.md     項目文檔
├── api    存放相關(guān)接口
├── components   存放相關(guān)組件
├── config   存放相關(guān)配置
├── eventBus.js    事件總線
├── filters   存放相關(guān)過濾器
├── main.js   入口文件
├── manifest.json    打包配置文件
├── node_modules   項目依賴包
├── package-lock.json    依賴包版本
├── package.json    包配置文件
├── pages    存放頁面
├── pages.json   頁面配置
├── static   存放靜態(tài)資源
├── store    vuex目錄
├── styles   全局樣式目錄
├── uni.scss   全局scss變量
├── unpackage    項目打包文件
└── utils    相關(guān)工具函數(shù)
服務(wù)協(xié)議配置

應(yīng)用上傳應(yīng)用寶,需要在下載首頁展示用戶協(xié)議和隱私政策彈窗提醒, 以及在應(yīng)用內(nèi)有查看的位置, 登錄或者注冊頁面有同意服務(wù)協(xié)議和隱私政策的提醒.
用戶協(xié)議和隱私政策彈窗提醒:
1.在uniapp項目manifest.json文件的源碼視圖中,找到app-plus
2.在app-plus節(jié)點下,添加privacy

"privacy" : {
            "prompt" : "template",
            "template" : {
                //prompt取值為template時有效,用于配置模板提示框上顯示的內(nèi)容
                "title" : "服務(wù)協(xié)議和隱私政策",
                "message" : "  尊敬的用戶,歡迎您注冊成為本應(yīng)用用戶,在注冊前請您仔細(xì)閱讀<a                 href='這里需要寫個單獨展示用戶協(xié)議的jsp或者HTML頁面'>《用戶協(xié)議》</a>及<a href='這里需要寫個單獨展示隱私政策的jsp或者HTML頁面''>《隱私政策》</a>,了解我們對您使用我們APP制定的規(guī)則,您個人信息的處理以及申請權(quán)限的目的和使用范圍。<br/>  經(jīng)您確認(rèn)后,本用戶協(xié)議和隱私權(quán)政策即在您和本應(yīng)用之間產(chǎn)生法律效力。請您務(wù)必在注冊之前認(rèn)真閱讀全部服務(wù)協(xié)議內(nèi)容,如有任何疑問,可向本應(yīng)用客服咨詢。",
                "buttonAccept" : "我知道了",//繼續(xù)下一步
                "buttonRefuse" : "暫不使用"http://退出下載
            }
}

提示:
在第一次下載應(yīng)用時出現(xiàn)此彈窗;
不能真機測試.測試需打包;

App引導(dǎo)頁

我們在pages目錄下新建4個頁面,分別為init,guide,index,login,在pages.json中會自動生成頁面路徑,將init頁面放在首位。
當(dāng)我們進(jìn)入到應(yīng)用時,首先進(jìn)入init頁面,onLoad鉤子下去判斷當(dāng)前用戶是否為第一次進(jìn)入,如果是則跳轉(zhuǎn)到guide引導(dǎo)頁面,如果不是,則再去判斷用戶是否登錄,如果已登錄則跳轉(zhuǎn)到首頁,如果未登錄,則跳轉(zhuǎn)到登錄頁面。這里init作用相當(dāng)于做一個路由中轉(zhuǎn)的作用。具體的實現(xiàn)方案我們可以參考下面的方案
Uni-App 啟動頁和引導(dǎo)頁介紹

app更新機制

App端的升級,又分為整包更新和資源熱更新兩種。

  • 整包更新,即常規(guī)的整個App安裝包重新下載安裝。
  • 資源熱更新,即App并重新安裝,里面的js等前端代碼進(jìn)行更新。

資源熱更新實現(xiàn)起來比較麻煩,這里我們重點介紹下整包更新。

Android App,可以直接下載新的apk,只要包名和證書不變,就可以覆蓋安裝。

接口約定

如下數(shù)據(jù)接口約定僅為示例,開發(fā)者可以自定義接口參數(shù)。

請求地址:https://www.example.com/update

請求方法:GET

請求數(shù)據(jù):

{  
    "appid": plus.runtime.appid,  
    "version": plus.runtime.version  
}

響應(yīng)數(shù)據(jù):

{  
    "status":1,//升級標(biāo)志,1:需要升級;0:無需升級  
    "note": "修復(fù)bug1;\n修復(fù)bug2;",//release notes  
    "url": "http://www.example.com/uniapp.apk" //更新包下載地址  
}
客戶端實現(xiàn)

App啟動時,向服務(wù)端上報當(dāng)前版本號,服務(wù)端判斷是否提示升級。

在App.vue的onLaunch中,發(fā)起升級檢測請求,如下:

onLaunch: function () {  
    //#ifdef APP-PLUS  
    var server = "https://www.example.com/update"; //檢查更新地址  
    var req = { //升級檢測數(shù)據(jù)  
        "appid": plus.runtime.appid,  
        "version": plus.runtime.version  
    };  
    uni.request({  
        url: server,  
        data: req,  
        success: (res) => {  
            if (res.statusCode == 200 && res.data.status === 1) {  
                uni.showModal({ //提醒用戶更新  
                    title: "更新提示",  
                    content: res.data.note,  
                    success: (res) => {  
                        if (res.confirm) {  
                            plus.runtime.openURL(res.data.url);  
                        }  
                    }  
                })  
            }  
        }  
    })  
    //#endif  
}

注意:App的升級檢測代碼必須使用條件編譯,否則在非App環(huán)境由于不存在plus相關(guān)API,將會報錯。升級地址URL,如果是自行托管的App,就提供自己的包下載地址。

服務(wù)端實現(xiàn)

PHP代碼:

header("Content-type:text/json");  
$appid = $_GET["appid"];  
$version = $_GET["version"]; //客戶端版本號  
$rsp = array("status" => 0); //默認(rèn)返回值,不需要升級  
if (isset($appid) && isset($version)) {  
    if ($appid === "__UNI__123456") { //校驗appid  
        if ($version !== "1.0.1") { //這里是示例代碼,真實業(yè)務(wù)上,最新版本號及relase notes可以存儲在數(shù)據(jù)庫或文件中  
            $rsp["status"] = 1;  
            $rsp["note"] = "修復(fù)bug1;\n修復(fù)bug2;"; //release notes  
            $rsp["url"] = "http://www.example.com/uniapp.apk"; //應(yīng)用升級包下載地址  
        }  
    }  
}   
echo json_encode($rsp);  
exit;

注意:版本檢測需要打包app,真機運行基座無法測試。因為真機運行的plus.runtime.version是固定值。

uni-app使用npm包
執(zhí)行  npm init  命令,初始化package.json文件
安裝moment:
 npm install moment -S
和我們在vue中使用npm包操作相同,
import moment from 'moment'
引入后即可使用

注意:uni-app 是跨端app,一些關(guān)聯(lián)dom和bom的npm包只能在uni-app打包為h5頁面才能使用。

uni-app全局配置

我們在pages.json中配置好我們的頁面路徑、標(biāo)題欄、底部選項卡后,像使用easycom組件自動化引入也需要在里面進(jìn)行配置,具體的配置項請查閱官方文檔。

請求封裝

我們的一款app脫離了服務(wù)端是沒有靈魂的,我們的項目基于restful風(fēng)格對原生的uni.request進(jìn)行了二次封裝,當(dāng)然,不同公司對請求封裝的要求不同,這里給出我的封裝方案供大家參考:

//  utils/request.js

import { baseUrl } from '@/config/baseUrl.js'
import util from '@/utils/index.js'
import { httpErrorStatusMessage, codeErrorStatusMessage, errorMessageSet } from '@/config/errCode'
// 返回header對象
const createHeader = () => {
    const header = {}
    header['Content-Type'] = 'application/json;charSet=UTF-8'
    const token = uni.getStorageSync('access_token')
    header['access_token'] = token ? token : '';
    return header
}

// 全局錯誤異常處理
const requestThrowError = (err = {}, type = 'fail') => {
    if(type == 'fail') {
        const { errMsg } = err
        if(errorMessageSet[errMsg]) {
            util.showToast(errorMessageSet[errMsg],'tip');
            return err
        }
    } else {
        const { data, statusCode } = err
        if(statusCode == 401) {
            return userPermissError(err)
        } 
        util.showToast(data.message,'fail')
        return new Error(data.message)
        
    }
}

// 權(quán)限處理
const userPermissError = (err) => {
    const { data } = err
    util.showToast('登陸過期','tip')
    // 清空token 用戶信息 跳轉(zhuǎn)到登錄頁面 start
    
    // end
    return new Error(data.message)
}

// 創(chuàng)建請求
const createReqInstance = (url = '',method = 'GET',data = {}) => {
    return new Promise((resolve,reject) => {
        uni.request({
            url:baseUrl + url, // 請求地址
            data, // 請求數(shù)據(jù)
            header:createHeader(), // 請求頭
            method, // 請求方法
            dataType:'json', // 返回數(shù)據(jù)首先JSON.parse
            // #ifdef H5
            withCredentials:false, // 跨域請求是否攜帶cookies
            // #endif
            
            // #ifdef APP-PLUS
            sslVerify: false,  // 安卓端不驗證ssl證書
            // #endif
            
            success(res) { // 請求成功
                console.log(res)
                const { data,statusCode } = res;
                if(statusCode != 200 || data.code != 0) {
                    const err = requestThrowError(res,'success')
                    reject(err)
                } else {
                    resolve(data)
                }
            },
            fail(err) { //請求失敗
                console.log(err)
                // 超時err.errMsg  "request:fail timeout"
                err = requestThrowError(err,'fail')
                reject(err)
            },
            complete() { // 請求成功或失敗最后都會執(zhí)行
                
            }
        })
    })
}

const getRequest = (url,params = {}) => {
    return createReqInstance(url,'GET',params)
}

const postRequest = (url,params = {}) => {
    return createReqInstance(url,'POST',params)
}

const putRequest = (url,params = {}) => {
    return createReqInstance(url,'PUT',params)
}

const deleteRequest = (url,params = {}) => {
    return createReqInstance(url,'DELETE',params)
}


export default {
  get: getRequest,
  post: postRequest,
  put: putRequest,
  delete: deleteRequest
}

// config/baseUrl.js


const baseUrls = {
    'development':'http://xxx.xxx.xx.xx:3000',
    'production':'http://www.production.com'
}

const baseUrl = baseUrls[process.env.NODE_ENV]

export {
    baseUrl
}

// config/errCode.js


const httpErrorStatusMessage = {
    
}

const codeErrorStatusMessage = {
    
}

const errorMessageSet = {
    "request:fail timeout":"請求超時"
}


export {
    httpErrorStatusMessage,
    codeErrorStatusMessage,
    errorMessageSet
}

// 

我們針對請求,封裝了get post put delete 四種請求,自定義請求頭,全局錯誤異常處理,權(quán)限處理,請求超時處理等等。

工具函數(shù)封裝

我們在util/index.js文件中封裝了一些常用的工具函數(shù),像校驗類,字符串類,數(shù)組類,正則類等等,下面給出一些對loading和toast的封裝

const showLoading = (title = '',mask = true) => {
    uni.showLoading({
        title,
        mask
    })
}
const hideLoading = () => {
    uni.hideLoading();
}

const showToast = (title = '',icon = 'none',image = '',mask = false,duration = 2000,position = 'center') => {
    const filterImage = (icon) => {
        let imageUrl;
        switch(icon) {
            case 'success': imageUrl = '/static/images/public/check-circle.png';break;
            case 'fail': imageUrl = '/static/images/public/fail-circle.png';break;
            case 'tip': imageUrl = '/static/images/public/info-circle.png';break;
            default: imageUrl = '';break;
        }
        return imageUrl
    }
    
    uni.showToast({
        title,
        icon: icon,
        image:filterImage(icon),
        mask,
        duration,
        position
    })
}

const hideToast = () => {
    uni.hideToast();
}



export default {
    typeFn,
    strRegexp,
    arrayFn,
    stringFn,
    numberFn,
    otherFn,
    showLoading,
    hideLoading,
    showToast,
    hideToast
}

// main.js

···
import util from '@/utils/index'
···
Vue.prototype.$util = util
// 最后我們掛載到Vue原型上,我們就可以通過this.$util.xxx來訪問工具函數(shù)
集成插件

下面介紹下我們項目中常用的一些插件

// 獲取網(wǎng)絡(luò)狀態(tài)
uni.getNetworkType({
    success(res) {
        console.log(res)
        const { networkType } = res
        let result = {
            isConnected:true,
            networkType:''
        }
        result.isConnected = networkType == 'none' ? false : true,
        result.networkType = networkType
        store.dispatch('network/setNetwork', result);
    }
})

// 監(jiān)聽網(wǎng)絡(luò)變化
uni.onNetworkStatusChange(function(res) {
    console.log(res)
    store.dispatch('network/setNetwork', res);
});

我們使用vuex存儲網(wǎng)絡(luò)狀態(tài),監(jiān)聽網(wǎng)絡(luò)變化,關(guān)聯(lián)網(wǎng)絡(luò)組件顯隱。

配置豎屏鎖定
// App.vue

···
onLaunch: function() {
            // #ifdef APP-PLUS
            plus.screen.lockOrientation('portrait-primary'); // 豎屏鎖定
···
}
main.js

下面我們通過查看main.js,將我們余下的工作整理完畢

import Vue from 'vue'
import moment from 'moment'

import store from './store'

import App from './App'

import '@/filters/index'
import '@/config/index'
import util from '@/utils/index'

Vue.config.productionTip = false

Vue.prototype.$util = util
Vue.prototype.$store = store
Vue.prototype.$moment = moment
Vue.prototype.$moment.locale('zh-cn')

App.mpType = 'app'

const app = new Vue({
    ...App
})
app.$mount()

  • vuex封裝,我們是采用modules的方式使用命名了空間將vuex的狀態(tài)進(jìn)行模塊化拆分,大家根據(jù)需要自定義封裝即可。
  • 我們在App.vue中引入了一些全局樣式,如下:
// App.vue
<style>
@import url("@/styles/index.scss");
</style>

// styles/index.scss
@import url("@/styles/font/iconfont.css");   // 字體圖標(biāo)css
@import url("@/styles/animate.min.css");  // 動畫css
@import url("@/styles/uCharts.css");  // 圖標(biāo)css
@import url("@/styles/common.scss");  // 公共css
@import url("@/styles/thorUI.scss"); // UI庫樣式二次封裝

總結(jié)

到此為止呢,我們的uni-app項目架構(gòu)搭建完畢了,當(dāng)然,我們也可以在uni.scss中添加一些全局scss變量,在README.md中撰寫相關(guān)的項目文檔??傊瑄ni-app的出現(xiàn)為我們的開發(fā)工作帶來的方便,以前開發(fā)這一套,我們需要安卓團隊,IOS團隊,前端團隊,三隊人馬,uni-app的出現(xiàn)大大提升了我們的生產(chǎn)效率,在此向DCloud公司致敬。學(xué)好uni-app,需要我們在實踐中不斷摸索,在需求中不斷的突破自己,uni-app的好多內(nèi)容等著我們?nèi)ヌ剿鳌I駱屖侄际亲訌椢钩鰜淼?,無他,惟手熟爾。大家加油??!

參考鏈接:
uni-app官網(wǎng)

我是前端dog君,一名95后前端小兵。對前端的熱愛,讓我們在此相聚,希望這篇文章,能幫助到您,也同時希望能交到志同道合的小伙伴,共同發(fā)展,一起進(jìn)步。我的微信號dm120225,備注簡書,期待您的光臨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容