曾經我覺得已通過了看偶像劇的年紀,後來無心中看了泰版浪漫滿屋,而後控寄不住寄己的體內的洪荒之力,繼續追完了泰版的惡做劇之吻,--有顏+演技時刻在線(雖然仍是偶像劇狗血套路,不過不影響我被圈粉)。我突然發現,原來熱情還在,只是如今大多國內的流量小生小花們已經挑逗不到我了。看看國內如今的電視劇,生硬的臺詞,僵硬的表情,像一盆盆冷水一點點澆涼我對劇的熱情,有時候不由會想,難道沒人對本身的做品負責嗎?哦,你們並無進錯房間,這不是在聊電視劇,咱這仍是技術文,因此我就不繼續吐槽置評了,我曾經下定過決心,只要一天還在出做品,就要對本身的東西負點責任。情懷,是個好東西,得留着點。回到咱們的主題,咱這個小框架再不濟也是個框架,得起個名字先。我被這兩部泰劇圈粉主要是由於女主aom可愛又認真的戲,乾脆就叫aom了,並且我但願這是個方便任意玩耍,輕量迷你的小框架,因此,我給它起個名字叫作--aomini。你們不要被我帶跑偏了,我安利的不是這兩個泰劇,是介紹個人aomini,😄。
先回顧上一篇我只是用最簡單的代碼介紹了一下aomini的思路,那樣的破磚爛瓦不修整一番怎麼能用呢?好了,接下來我就帶着你們一塊兒來修整一番。vue
若是你們不記得上一篇講的啥破磚爛瓦,能夠戳這裏回去看看。上一篇徹底是以糊塗流水帳的形式蓋的破瓦房,房屋結構啥的都是一股腦疊上去的,毫無結構可言,接下來咱們來將這個破房子分解一下。首先,底層結構跟上層結構得先拆開,底層結構屬於libs,上層結構就是業務邏輯,也就是咱們肉眼可見的那一層,入口文件,以及那幾個模塊文件確定都屬於業務邏輯了,至於store,Provider和connect函數確定屬於libs範疇了。拆解後文件結構以下所示,react
let store = {
//目標組件對象
contexts:[],
//state數據
state:{
m1Var:"111"
},
//註冊綁定組件與狀態數據,用於setState
bindContext(_context){
this.contexts.push(_context);
return this.state;
},
unbindContext(_context){
for(let i = 0; i < this.contexts.length; i++){
if(this.contexts[i] === _context){
this.contexts[i] = null;
console.log(_context);
}
}
},
setState(bs_state,context){
let newState = Object.assign(this.state,bs_state);
console.log(".......",newState)
// this.state = {};
this.contexts.map((item)=>{
if(!item) return;
React.Component.prototype.setState.call(item,bs_state);
})
}
}複製代碼
store沒有作太大變化,只是完善了一下,組件裝載時,調用bindContext將組件的上下文關係添加到contexts列表,當數據中心狀態變化時,調用store的setState方法,該方法實質是將全部綁定的組件進行setState調用。如此,便簡單實現了狀態變化與UI的數據流關係。
每一個組件都須要接收store對象,所以就須要將store放入頂層父組件的context中,也就是Provider這個入口組件,該組件代碼以下:git
class Provider extends React.Component{
getChildContext(){
return {
store:this.props.store
}
}
constructor(props){
super(props);
}
render(){
return React.Children.only(this.props.children);
}
}
Provider.childContextTypes = {
store:PropTypes.object
}複製代碼
該組件與redux中同樣,子組件只接受單個元素。而後就是將props中傳入的store元素進行變量的全局化,固然這裏暫時實現比較粗暴,咱尚未作到像redux同樣過多考慮個性化擴展,但說白了redux實現核心也就是這麼個玩意兒。
接下來咱們再回過頭來觀察一下上一篇的組件代碼,每個模塊都有一堆樣板代碼,store.bindContext(this);尤爲以前只是單文件簡單的合併寫法,模塊拆成獨立文件後,store又是須要從上下文中引用的,所以樣板代碼至少又這些:
1,組件裝載的時候github
let store = context.store;
store.bindContext(this);複製代碼
2,組件卸載的時候須要移除被卸載的組件綁定關係web
componentWillUnmount(){
this.store.unbindContext(this);
}複製代碼
每一個組件都要在邏輯中如此調用,須要封裝一下,何況,業務組件最好只關注業務點,這種非業務邏輯的樣板代碼不應出如今業務組件中,那這種通用邏輯調用的狀況下,咱們的高階組件就須要派上用場了。相似redux中的connect組件代碼以下:redux
let connect = function(wrappedCompo){
class ConnectHoC extends React.Component{
constructor(props,context){
super();
this.store = context.store;
this.store.bindContext(this);
}
render(){
return React.createElement(wrappedCompo,{store:this.store});
}
componentWillUnmount(){
this.store.unbindContext(this);
}
}
ConnectHoC.contextTypes = {
store:PropTypes.object
}
return ConnectHoC;
}複製代碼
這個connect高階組件接收一個實際業務組件爲參數,返回一個包含該組件的新組件,並實現了store經過props的傳遞,實際業務組件獲取store直接從props便可,也許你會問store已經存在context中,直接去取就是了,爲啥還要經過props傳入,仍是同樣的道理,那樣的話業務組件會多一些獲取全局變量的樣板代碼,而且違背了業務組件只須要關注業務的原則。好了,如今這麼一來,咱們的業務組件只須要關注本身的業務點以及數據在哪裏獲取,無需過分關心其餘。
而且就跟react-redux中使用是同樣的,組件都使用connect進行包裝便可,僞代碼以下:bash
class Module extends React.Component{
constructor(){
super();
}
render(){
}
}
let ModuleHoC = connect(Module);複製代碼
所以,Provider組件下的全部通過connect包裝過的組件裝載都會自動進行上下文綁定,並使用store集中管理數據狀態,當狀態改變,全部綁定的組件進行setState操做,即完成了UI的更新。架構
很明顯,這個設計思路就是來源於react-redux的設計思想,react-redux是個好東西,只是我在實踐中發覺,react自己其實已經至關好用了,只是有些地方好比狀態管理部分只用原生react的話,開發過程會變得十分不優雅,既然如此,那咱們或許只須要將react中不那麼優雅的東西適當摺疊修整一番,就能變得更好用了。react-redux中強調邏輯與視圖之間徹底分離,這是很好的思想,可是不管flux或者redux的設計初衷,其實都是爲了更合理地管理狀態而來的,react的設計本來就並未將UIrender與邏輯徹底割裂,並不是像vue中將template徹底進行了剝離。何況,邏輯與UI的分離並不是必須分到兩個不一樣的文件中去纔是分離,這樣反而從編碼層面上帶來很多的干擾,缺乏碼代碼的快感。
不過目前來講,aomini雖然實現了功能,可是絕對比不上react-redux在總體設計上的優雅。react-redux是基於redux的動做訂閱模式,使用了監聽者模式,每個模塊的設計都是根據單一職責的原則,UI中觸發state的更新必須經過派發一個action,經過監聽器進行監聽每個action,不過這裏的監聽器是弱化了的,並無針對每個action進行細分監聽,這裏你們須要注意,其實這個設計是很巧妙且又合理的,由於react是基於狀態變化的,而非咱們以前熟悉的命令式開發模式,一切都是圍繞總體的狀態,而非某個動做,所以不管action如何指示,最終只是轉化成總體狀態變化的讀取。reducers進行狀態計算,並使用connect組件的參數mapStateToProps函數做爲狀態選擇器,進行子狀態select,完美地解決了特定狀態的讀取,以上處理就優雅地完成了UI=>store=>action=>reducer=>UI這樣一個完整閉環。aomini上有flux和react-redux的影子,可是本質上來講,到目前爲止,aomini跟後二者並非同一種東西,flux是一套完整的web架構思想,react-redux是從flux發展而來的比較完善的開發框架,而aomini是從二者之中取出的部分思想,變得更加靈活,儘管不算是一個完整的框架,不過我從實際開發中感覺到,配合本來已經足夠完美的react,已經夠用了。app
框架上的東西沒有絕對的好與很差,殺雞用牛刀何嘗不可,只是這把刀不可過重,否則殺只雞比宰一頭牛還累,虧本買賣。一個小工程,總共業務幾句代碼,非得上一堆牛逼哄哄的框架,最後出來幾大m的代碼量,反而拖累頁面效率,這不就是得不償失。以上對aomini的核心代碼設計思路介紹了一下,目前只是一些核心骨幹代碼,後續接下來就是須要繼續完善其中的細節,代碼已上傳github,並實時進行更新,有興趣的同窗們就敬請關注了。但願跟你們一塊兒交流。
須要的同窗,能夠戳這裏簽出代碼:react-aomini
會繼續實時更新,歡迎各位拍磚!框架