最近公司有一個微信公眾號的項目旧找,于是花了一定的時間去搭建關于一個可以用于開發(fā)的微信公眾號的架子。技術選型使用了阿里的dva核畴。
- 第一步域慷,使用
dva new wechat-public
來初始化腳手架。 - 第二步总寻,完善當前腳手架器罐。搭建一個架子無非就從這幾點來操作:
- 網(wǎng)絡層(api接口,service服務)渐行。
- 業(yè)務層(使用dva基于redux的數(shù)據(jù)流方案轰坊,在models中定義數(shù)據(jù)源,以及業(yè)務操作)
- 路由(使用dva基于react-route搭建頁面路由祟印,并且基于react-router搭建一個靈活的可控路由)
- 靜態(tài)資源庫的存放(文件夾assets中)
- 組件庫的存放(文件夾components中)
- 頁面存放(文件夾pages中)
- 工具類(文件夾utils)
- 網(wǎng)絡層的構造肴沫。
我們選取axios作為網(wǎng)絡層請求的基本庫。對其進行封裝蕴忆。在封裝后颤芬,遇見了一個跨域請求的問題,原來是withCredentials
犯的錯誤。
經(jīng)查詢站蝠,有以下的解釋汰具,參考:
XMLHttpRequest.withCredentials 有什么用?
跨域請求是否提供憑據(jù)信息(cookie、HTTP認證及客戶端SSL證明等)
也可以簡單的理解為菱魔,當前請求為跨域類型時是否在請求中協(xié)帶cookie留荔。
XMLHttpRequest.withCredentials 怎么用?
withCredentials屬于XMLHttpRequest對象下的屬性,可以對其進行查看或配置澜倦。
- 數(shù)據(jù)的流向與頁面路由
利用dva自帶的redux的封裝聚蝶,我們可以查看models層是mvc中的控制層的作用。首先通過在services中創(chuàng)建一個js文件肥隆,將我們的網(wǎng)絡請求的服務暴露出來既荚,然后再通過models層中的effects去交互。具體的可以去dva官網(wǎng)學習栋艳。
期間遇到的問題:
1.如何全局監(jiān)聽整個頁面的路由恰聘。
我們可以在react-routes中來操作。首先吸占,我們創(chuàng)建一個app.js晴叨,來作為所有界面的父界面,然后矾屯,將其注冊在route中兼蕊。為以下的代碼
<ConnectedRouter history={history}>
<App>
<Switch>
{/* 默認跳轉到 service 頁面 */}
<Route exact path="/" render={() => <Redirect to="/service" />} />
{
Routes.map(({ name, path, exact = true,...dynamic_d }) => (
<Route path={path} component={dynamic({app,...dynamic_d})} exact={exact} key={name}></Route>
))
}
</Switch>
</App>
</ConnectedRouter>
其中ConnectedRouter為dva-redux中暴露出來的Router,可以使用redux檢測整個路由的變化件蚕,若我猜的不錯孙技,應該可以使用routerRedux
去跳轉路由,隨后排作,使用在Switch外層包裹App牵啦,此App即為我們所需要封裝的層。首先感謝這篇文章給我啟發(fā)妄痪,隨后哈雏,我們使用connect來將此組件包裹,connect為dva控制流的一個銜接衫生。并且裳瘪,我們需要在models中來注冊這個model,這里需要注意一個問題罪针,就是WithRouter的使用彭羹,由于這個頁面是初始化頁面,所以router還沒有注冊進來站故,我們用WithRouter讓其props中的push,pop等方法注冊進來皆怕,這樣我們就可以在其中進行頁面控制毅舆。隨后,我們則可以通過綁定的app控制層來控制當前頁面的路由愈腾。在models中使用:
subscriptions: {
setup({ dispatch, history }) { // eslint-disable-line
},
setupHistory({ dispatch, history }) {
history.listen((location) => {
//當前監(jiān)聽全局的路由變化
console.log(location)
})
}
},
- 如何通過dva-loading來控制整個項目的loading憋活。
這個問題是一個比較需要關注的問題,因為之前我有用dva來做項目虱黄,由于當時對dva不是特別的熟悉悦即,所以還沒有將其發(fā)揮極致,最后loading是自己寫一個界面橱乱,然后在每個界面都在request后面來使用辜梳,導致每個界面都需要首先注冊一個state的isshow(舉個例子)來控制loading的顯示和隱藏。這極大的讓整個項目的代碼冗余泳叠,并且消耗時間作瞄。
直到查詢loading的控制后,發(fā)現(xiàn)整個組件危纫,并且可以通過整個項目的數(shù)據(jù)流來控制宗挥。在index.js中注冊這個后:
const app = dva({
...createLoading({
effects: true,
}),
history: createHistory(),
onError (error) {
Toast.fail(error.message);
},
});
隨后,我們可以通過connect將loading注入到組件組件中种蝶,并且組件中會有
effes/user
來控制單個的異步請求,這樣空民,我們就可以通過App來全局控制整個loading了,極大的減少了我們的工作量序矩。在其他頁面,只要connect就可以獲取當前頁面的異步請求,是不是特別的簡單。另外裸燎,我們需要注意一些路由的問題,v3和v4的寫法不同泼疑,具體看官網(wǎng)。
- 關于dva的動態(tài)加載組件的問題荷荤。
在寫這個架子之前退渗,我有寫一個mobx的控制流架子,里面動態(tài)組件是通過react-loadable
蕴纳,但是dva項目中已經(jīng)有屬于他的一個動態(tài)組件加載会油。那就是dynamic。
如何使用? 這邊剛好可以通過這個古毛,把我們的按業(yè)務加載model也給寫下來翻翩。
//tabs
const pagingTabs = [
{
name: '就診服務',
path: '/service',
models: () => [
import('models/service'),
],
LoadingComponent:MyLoadingComponent,
component:()=> import("pages/index")
},
{
name: '個人中心',
path: '/center',
LoadingComponent:MyLoadingComponent,
models: () => [
import('models/center'),
],
component:()=> import("pages/index")
},
{
name: '醫(yī)院信息',
path: '/hospital',
LoadingComponent:MyLoadingComponent,
models: () => [
import('models/hospital'),
],
component:()=> import("pages/index")
}
]
以上是一個路由的封裝都许,將所有的路由都封裝到這個pagingTabs
里面,然后嫂冻,我們通過上面的代碼注冊路由即可胶征。
注意:在component中,我們不能夠直接導入組件桨仿,而是要通過方法來回調出組件睛低,這樣才能夠實現(xiàn)異步加載。
具體參考:React最佳實踐
- 關于dva無法使用二級路由的問題服傍,一直報錯:
unexpect token <
此錯誤困惑我很久钱雷,無法明白dva的問題。但也由于粗心的問題吹零,第一我們得分清楚hashhistory和browerhistory的區(qū)別罩抗,然后,我們不能使用dva自帶的history去注冊路由灿椅,而是需要使用第三方庫history
套蒂,下載后,通過以下來注冊:
import { createHashHistory as createHistory } from 'history';
const app = dva({
...createLoading({
effects: true,
}),
history: createHistory(),
onError (error) {
Toast.fail(error.message);
},
});
browerhistory 頁面是無法出來的阱扬,會是空白頁面或者報錯泣懊,是因為項目中無法找到這個頁面,我們得使用hash來讓頁面顯示出來麻惶,記得在前面中加#
馍刮。
- 關于dva的
.webpackrc
文件和.roadhogrc
文件
其實這兩個文件相同,只是因為dva最新版把roadhogrc改為了webpackrc,其中語法可以參照roadhogrc中窃蹋,我們在使用這個框架的時候卡啰,在github中去尋找這個庫,這個只是creact-react-app中的一個擴展警没,讓我們不用通過eject就可以自定義整個webpack匈辱。
當然,我們還可以自己創(chuàng)建一個webpack.config.js
來自定義webpack杀迹,比如我寫了:
module.exports = (webpackConfig, env) => {
// 別名配置
webpackConfig.resolve.alias = {
'pages':`${__dirname}/src/pages`,
'components':`${__dirname}/src/components`,
'utils':`${__dirname}/src/utils`,
'routes':`${__dirname}/src/routes`,
'models':`${__dirname}/src/models`,
'services':`${__dirname}/src/services`,
'models':`${__dirname}/src/models`,
'@':`${__dirname}/src`
}
return webpackConfig
}
來定義alias亡脸,讓文件容易讀取。
- 關于html-plugin插件
我們使用這個插件來定義我們整個項目的入口模板树酪,并且可以通過他自動生成Html浅碾,通過filename來指定html生成的路徑。此項目中使用entry.ejs
來定義入口续语。
整個框架:dva + axios + antd-mobile + react-router + roadhog
另感謝這些作者:
React最佳實踐系列 —— Dva 進階之路由和動態(tài)加載
DVA框架統(tǒng)一處理所有頁面的loading狀態(tài)
ajax中的withCredentials使用效果
dva