react服务端/客户端,同构代码心得
react服務(wù)端/客戶端,同構(gòu)代碼心得
作者:webkixireact服務(wù)端/客戶端,同構(gòu)代碼心得
服務(wù)端,客戶端同構(gòu)一套代碼,大前端的夢想,為了省略重復(fù)的代碼,卻平添了不少煩惱,頭發(fā)也白了,。。。。,妹子還在家等我.
目錄結(jié)構(gòu)問題
我們引用了很多的庫,在開發(fā)前端代碼的時候,習(xí)慣性的我們不會考慮到node端對于庫的引用,這就是開始同構(gòu)最大的痛點(diǎn)。整個目錄結(jié)構(gòu)需要調(diào)整。
減少調(diào)用層級
比如說開發(fā)前端時,有一個libs的庫,在react的前端組件開發(fā)時,我們多次調(diào)用到libs里面的若干方法,這個時候,為了同構(gòu),需要將libs庫做一個抽離,既是從前端代碼中抽離到中間的部分。
這么說有點(diǎn)不好理解,簡單配一個圖吧。
FKP原來的結(jié)構(gòu)
node -> fed -> libs -> component -> pages
大致上我們原來的結(jié)構(gòu)都類似于這樣,調(diào)整好之后的結(jié)構(gòu),如下:
node <-> libs <-> fed -> component -> pages
這樣,我們將libs抽離到中間的部分,相對來說,在同構(gòu)時,require的層級少了很多。但是還不夠,為了 將react同構(gòu),我們還需要調(diào)整component的結(jié)構(gòu),如下:
node <-> libs <-> component <-> fed -> pages
如此這般,大致的結(jié)構(gòu)算調(diào)整好了,接下來解決require的坑,讓webpack和node端require做到無縫切換。 讓require('libs/index'),這種引用兼容于兩端。 在這里FKPJS用到了一個好用的包文件app-module-path,指定node端require的目錄優(yōu)先級,及自寫了一個 include的方法(封裝require),來簡化require的調(diào)用深度。 并對libs庫做更細(xì)化的抽象與提取,最后,FKPJS的libs結(jié)構(gòu)做到如上所述。
組件結(jié)構(gòu)問題
解決了目錄結(jié)構(gòu)問題后,為了做到同構(gòu),我們需要合理的組件結(jié)構(gòu),以方便兩端的調(diào)用,經(jīng)過本人的實(shí)踐,FKPJS將組件分為三層,原子組件,組合組件,組件封裝,如下圖
原子 -> 組合 -> 封裝
1. 原子組件(react/widgets)
適用node/fed,復(fù)用型組件,最小粒度化,產(chǎn)出純結(jié)構(gòu),純粹的react組件,封裝了對數(shù)據(jù)的處理
2. 組合組件(react/modules/xxx/_component/xxx)
適用node/fed,組合不同的原子組件,并引入相關(guān)mixins,實(shí)現(xiàn)like redux,產(chǎn)出純結(jié)構(gòu),純react組件,傳輸數(shù)據(jù)
3. 組件封裝(react/modules/xxx/yyy)
適用于前端,最表層,處理配置文件,可導(dǎo)入JQ等庫實(shí)現(xiàn)內(nèi)部邏輯、效果,并響應(yīng)由業(yè)務(wù)層傳導(dǎo)進(jìn)來的方法,數(shù)據(jù)等等。
在FKPJS中封裝的比較好的有兩個組件,react/modules/pagination/pagi,react/modules/list/base_list.jsx,list組件有點(diǎn)復(fù)雜,我們先說下 pagi這個組件吧
pagi這個組件,用于分頁,可前后端同構(gòu)
Demo
前端業(yè)務(wù)中實(shí)現(xiàn)的代碼
varPagi=require('modules/pagination/pagi'),// 初始化分頁數(shù)據(jù)pageData ={total:60,per:20,url:'/',query:'page='}Pagi(pageData,{container:'pagi',begin:{ start:0, off:5},itemMethod: bindItem })服務(wù)端同構(gòu)的代碼
// pages/pagi.jsvar _props ={itemMethod:false,listMethod:false,itemClass:'',listClass:'pagenation wid-12',data:{total:60,per:20,url:'/',query:'page='},begin:{ start:0, off:5}}var reactHtml =yield react2html('react/modules/pagination/pagi', _props)reactHtml[0]='<div class="pagi" id="pagi" >'+reactHtml[0]+'</div>'oridata.pagi = reactHtml[0]return.....組件封裝
封裝部分
// 封裝方法function pagination(data, opts ){// 處理配置文件 var noop =false,dft ={container:'',globalName:'_Pagi',itemMethod: noop,listMethod: noop,itemClass:'',listClass:'pagenation wid-12',data:{total:200,per:10,url:'/',query:'page='},begin:{ start:0, off:7}}dft = _.assign(dft, opts)if(!dft.container)returnfalse;if(data){dft.data = data}// fkp redux// 初始化組件數(shù)據(jù)// FKPJS使用SA代替redux// 需要在組合組件中引入,store的minxinSA.set(dft.globalName,{data: data,begin: dft.begin})// fkp redux // 將組建的action放到 SA 的全局名字中// 需要在 _Pagi組件中引入 store 這個mixinsvarPagi=_Pagi(dft.globalName)// 渲染組件render(<Pagi data={data}begin={dft.begin} itemDefaultMethod={idm} itemMethod={dft.itemMethod} listMethod={dft.listMethod} itemClass={dft.itemClass} listClass={dft.listClass}/>,document.getElementById(dft.container))}// 服務(wù)端同構(gòu),執(zhí)行這個部分 pagination.server =function(){return_Pagi(true)};module.exports = pagination組合組件
這里不貼出所有代碼,部分
varList=require('../../../widgets/listView/list');varStore=require('../../../mixins/store');//引入這個就完成了reduxvar _storeName;var _jump =false;// List的item組件varPageItem=React.createClass({componentDidMount:function(){var ele =React.findDOMNode(this),mtd =this.props.itemMethod,dmtd =this.props.itemDefaultMethod;if(dmtd &&typeof dmtd==='function'){dmtd.call(ele, _storeName, mtd);}},.......組合組件-算法部分
render:function(){if(this.state.data){var data =this.state.data,newData =[],pages = data.total/data.per,pre,aft,half,begin=this.state.begin,........組合組件-實(shí)現(xiàn)部分
function actRct( storeName ){// 根據(jù)storeName,可以實(shí)現(xiàn)多個組件,并redux化// for serverif(storeName===true){returnReact.createClass( pagenation );}// for client_storeName = storeName||'_Pagi';var _rct = _.cloneDeep(pagenation);if( _rct.mixins && _rct.mixins.length ){_rct.mixins.push(Store( _storeName ))//實(shí)現(xiàn)redux}else{_rct.mixins =[Store( _storeName )]}returnReact.createClass( _rct );//返回react組件原子組件
綜上所述,做到兩端同構(gòu)的話,需要有一個全局的眼光,從基礎(chǔ)的目錄結(jié)構(gòu)開始,到組件的結(jié)構(gòu),其實(shí)還有css的結(jié)構(gòu),html的結(jié)構(gòu),這里就不一一說明了,希望能拋磚引玉
文章目錄
轉(zhuǎn)載于:https://www.cnblogs.com/yzf851348507/p/5601060.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的react服务端/客户端,同构代码心得的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS工作笔记(十二)
- 下一篇: 0000000