閒話少敘,書歸正傳。
0x00 故事背景
在有限的人力成本情況下,需要按時上線產品,主要包括:
前端專案:小程式A(C端)、小程式B(B端)、PC管理端
後端專案:平臺API專案
其實站在後端開發來講,由於是服務於業務的系統,又是產品前期,所以也就Spring Cloud
一套打完,這裡主要想細說的是前端幾個專案的情況。
前端開發,在有些朋友描述中可能就是畫畫介面、獲取介面資料、調介面、顯示資料,然後一直重複著這個過程,就算使用了一些主流框架,也只是更好、更快的畫介面、獲取介面資料、調介面、顯示資料。其實,簡單(初級)的前端也好像真是這樣,要是真這麼理解,那人活著也多沒勁呀,整體就是吃、睡,哈哈哈~
其實自從前端開發宣佈獨立後,“階級矛盾”好像也就變成了業務邏輯的前置還是後置的矛盾。尤其是在一些“大前端”的實踐中,當然,我也有幸在其他地方看到過,整個後端服務就是一個簡單的CRUD服務了。問:後端服務主要做什麼用?答:為前端開發提供資料庫訪問介面。 哈哈,好像也不是沒有道理,站在安全的角度考慮,我一直建議業務邏輯後置的,前端儘量迴歸純資料展、互動就行。
0x01 鬼知道我怎麼想的
三個前端專案同步進行開發,那麼必然將會有大部分的工作量是重疊的。相信做開發的朋友應該也都瞭解,前端介面開發、模擬資料互動等工作都是可以直接人工堆出來了。但是,碰到介面聯調,再附加上業務聯調,多數會因為設計的不完善而造成改改改,在工期上一般會比較耗時。那麼這次就想著將三個專案的介面聯調給統一化。所以,為了達到統一,首先就需要解決的是微信小程式
和web
的介面請求了。
這裡不打算詳細介紹微信小程式技術,但是也放張圖(來自網上)出來,先了解一下為什麼要達到一統。
小程式示意圖
微信小程式本質也是一種Hybird App,於是乎熟悉的window、document物件被消失了,當然,也找不到XMLHttpRequest了,還Ajax個鬼。所以,也只能通過官方的wx.request
介面來發起網路請求。我們的目標是統一化,所以只能程式碼對wx.request
和 XMLHttpRequest
進行相容了。這裡順帶推薦一個開源專案Fly.js來作為HttpClien使用。
Fly.js
的設計剛好符合我們現階段的需求,很好的將API請求邏輯和具體的請求執行(引擎)進行了分離,開發人員只需要呼叫.get()
、.post()
等函式發起請求,至於是使用wx.request
還是XMLHttpRequest
,就是我們底層的配置了,與具體業務程式碼就沒有半點關聯了,對上層的請求呼叫邏輯,很好的遮蔽了底層的請求執行。
閒白:在以前的PC時代,曾一直喜歡桌面端工具開發,喜歡做一些小工具給大家玩兒。從C#的純桌面開發到WinFrom + WebKit,再到Silverlight、WPF,微軟一直不放棄的更新,可是總感覺一直在學習,從未被應用,哈哈哈,難道是我離坑太遠了? 一直到現在的Nodejs跨平臺技術,移動端的WebView等跨平臺技術,其實思想多數都是一樣的,只是一直在更新優化。
0x02 猶抱琵琶半遮面
瞭解過微信小程式開發的同學,應該都比較熟悉setData
函式,是的,和其他框架的setState
啥的都是一個作用,都是用來主動觸發渲染引擎的update
操作,最終執行效果是會通知框架渲染邏輯進行資料更新展示。
很好的一個函式,可是你見過滿螢幕的setData
邏輯麼?哈哈,我有看到過。setData
的濫用確實比較嚴重,一大段邏輯程式碼中,動不動就來一個setData
,尤其是再涉及到資料中key的N層巢狀問題,看著就發燥,是不是很懷念其他框架中的XXX.key = value
方式。
其實不然,就像有這麼一句話:當你感覺到輕鬆(方便)的時候,是因為有人在幫你承擔壓力。從編碼方式來看,直接賦值確實簡潔一些,但是相應帶來的卻是框架在一直監聽著你的set
操作,從效能上考慮的話,我還沒有做過具體的測試,會有多大影響,這個說不好。可我就喜歡直接賦值的方式,哈哈哈,任性。
到不完全是個人原因,而是從其他方面考慮。說了這麼多,這裡為什麼要先吐槽微信小程式的setData
呢,其實主要原因是,微信小程式自身目前並沒有很好的狀態管理容器,多數情況需要自己去實現簡易的管理,或者直接不使用。所以為了快速、方便的開發,必須要整合成熟的redux
或者vuex
來實現狀態管理。
由於PC版的技術優先確定了下來,需要使用iview-admin框架來開發,那麼開發人員使用vue
來做。那麼,考慮為了實現微信小程式專案與PC版的一些元件最大限度的複用,WePy還是mpvue的選擇上也就沒啥爭議了,管他什麼親兒子的,直接就確定mpvue了,因為都是vue
全家桶,哈哈,也要相應的考慮下開發人員的學習成本。
至此,整體的前端技術方案也就明確了下來:
小程式開發:mpvue
PC版開發:iview-admin
狀態管理:vuex
請求框架:Fly.js
接下來,對整體的技術方案進行下介紹。
閒白:叨叨了這麼久才算進入正題?列位也別嫌我絮叨,在家歇著天天一個人,就話多,哈哈。在以前的C#和Java Swing的開發中,各類元件處理資料展示,尤其是在多執行緒的情況下,UI主執行緒的控制元件同步訪問等問題,都是比較煩人的。記得那時有討論提出要將窗體繪製、資料展示、業務資料處理進行分離,應以資料為主線,資料的變更來驅動介面展示,而不應該是用介面邏輯來驅直接處理資料,應該是業務資料在某一個狀態應該由哪個介面來展示。記得當時還專門實現了一套基於外掛模式開發的框架,將專案的UI模組作為一個顯示外掛來使用,通過資料繫結來完成渲染展示。現在想來,也算比較符合當前的Flux思想。
0x03 整體介紹
整體方案確定後,那就按照相應的流程給大家畫一個整體設計圖
整體設計圖
從左向右來看
- 微信小程式基於mpvue開發,PC版使用iview-admin開發,分別來完成介面的開發和資料的互動。vue通過繫結Store中的資料來提供給介面渲染使用。
Store
為Vuex的狀態(資料)管理,通過actions
和mutations
提供相應的業務邏輯處理。在actions
中呼叫Services
的模組服務來完成API請求。Services
中的模組服務呼叫Fly.js來完成API請求執行。
這裡有一個地方在實際應用的時候需要考慮一下,那就是Store
和Services
的拆分。
其實這裡也有是一些顧慮的,如果拆分兩層的話,在開發工作量上會有所增加,如何合併都到Store
中也是可以的,直接在Store
通過HttpClient
(fly.js)來請求介面,然後完成響應資料解析處理,也不是不可。最後決定還是進行拆分,主要是不希望Store
中有太多的響應資料解析邏輯,應該更專注業務資料的邏輯處理,這樣也可以通過在Services
層中來模擬資料來進行快速測試,將Services
層作為一個輕薄的資料訪問(協議)層。
具體的示例程式碼來一下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//Services中的Article模組 import config from '../config' import http from '../util/HttpClient' //匯入介面配置 const { list } = config.article; //模組程式碼開始 export default { //宣告查詢介面 async query(params){ //POST引數,獲取響應資料 const {status,content} =await http.post(list, params) //過濾掉介面引數,只返回業務資料 if (http.isOk(status)) { return content } throw http.error(status); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Store中對服務呼叫 import articleService from '../../service/ArticleService' //Vuex state const state = { listData: [] } //actions宣告 const actions ={ /** * 查詢列表 */ async query ({commit, dispatch, state}, {op = 0}){ //呼叫服務獲取資料 const queryResult = await articleService.query(state.query); //... } } |
1 2 3 4 5 6 7 8 |
//vue元件使用 export default { computed: { listData () { return this.$store.state.article.listData } } } |
整體程式碼模組層級可以表示為這樣的:
整體層級圖
可以看到,我們將Store
放在了每個專案中來進行初始化,然後通過Vuex
的Module
模式,來按照需要的業務模組可以進行自由組合。
在小程式A示例程式碼中的Store
片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import Vue from 'vue' import Vuex from 'vuex' //匯入vuex modules //專案自有模組,必須要和其他專案共享 import UserModule from './modules/user' //公共模組,可與其他專案共享 import Activity from 'XXXX/store/modules/activity' import Article from 'XXXX/store/modules/article' import EnumModule from 'XXXX/store/enum' // Vue.use(Vuex) //小程式A的Store建立,組合需要的模組 export default new Vuex.Store({ modules: { user: UserModule, activity: Activity, article: Article, enum: EnumModule } }) |
當總體的設計都清晰了之後,那麼就該來看下專案的結構該如何組織。這裡按照上面所述,拆分了5個專案,具體結構如下:
專案圖
可以看出,這裡主要分為三個主專案(上層)和兩個支撐專案(下層)。支援的專案為公共專案,分別是XXXX-front-api
和mp-common
,以npm module
方式被小程式A、小程式B、Web管理平臺來進行依賴引用。
- XXXX-front-api:該專案主要為業務公共專案,包括共用的
Vuex Module
、各模組的Services
、Fly.js的封裝
以及常用的Utils
等。 - mp-common:該專案主要對微信小程式專案開發,對小程式的API進行封裝,將小程式API的
success
回撥轉換為Promise
方式,用以支援async/await
方式。提供共用的小程式元件
、樣式
、工具類
等。
接下來還要介紹下在專案搭建中要注意的問題,nodejs專案的建立這裡就不多說了,具體的npn init
或相關框架的腳手架
瞭解下,方便的很。
git中子專案使用
首先,使用git
來建立我們規劃的五個專案,其中有兩個公共模組專案,所以需要使用git submodule
的方式來在主專案中進行管理,結構如下:
1 2 3 4 5 6 7 8 9 10 11 |
#主專案-小程式A /mp-a.git /xxx-front-api.git /mp-common.git #主專案-小程式B /mp-b.git /xxx-front-api.git /mp-common.git #主專案PC版管理 /mc.git /xxx-front-api.git |
nodejs的本地模組使用
在nodejs
專案中,又涉及到公共模組專案的引用,在java maven
中,通常使用mvn install
來完成本地模組的安裝,而在nodejs
專案中,主要使用node_modules
檔案放置依賴,所以我們可以通過系統的軟連線
或者直接使用npm link
來完成本地模組的軟連線建立。這樣在三個主專案中任意一個專案中對依賴專案的修改可以讓其他專案達到同步使用。
1 2 3 4 5 6 7 |
#npm 安裝本地專案 npm link ./mp-common # #在nodejs專案中使用模組 npm install mp-common 或者 yarn add mp-common # #專案中就可以直接使用模組了 |
前面主要介紹了小程式選型mpvue
、跨平臺的API請求
、基於vuex的專案設計
,以及專案在搭建過程中需要注意的地方,這次主要以設計為主,具體mpvue在開發中的使用與問題,我們們且聽下回分解。