摘要:一個管理數據層的產品地址我們將定義為一個產品而不是一個框架亦或工具包。認識裝飾器,一切故事的開始,目前僅僅只有一個參數。我們對場景的定義多個頁面之間針對同一組業務數據進行的一連串行為動作來完成的一組業務,我們稱之為場景。
dingDang ( 一個管理react數據層的產品 )
github地址
我們將dingDang定義為一個產品而不是一個框架亦或工具包 。 因為dingDang在設計之初就將用戶的開發體驗放在第一位,而性能問題則放在第二位。 當然這并不意味著我們就是一個性能很糟糕的產品,只是說我們會在性能能夠接受的范圍內盡可能的去讓開發者的開發體驗更好。 事實上dingDang的內部數據全部都采用了immutable數據類型。 dingDang中使用了大量的 Promise 于 immutableJS , 如果你對此不太熟悉,可以先熟悉一下 這兩個知識點。認識 DingDang
DingDang裝飾器 , 一切故事的開始 , 目前 僅僅只有 sceneStorage 一個參數 。 主要用來定義場景的臨時數據存儲方案。 比如說: 在react-web 中 你應該采用sessionStorage 或者 localStorage , 而在react-native 中,你應該采用AsyncStorage 。 在sceneStorage中的3個函數 所有的返回值 要求是標準的 JS Object , set 方法的 key 我們也會傳輸一個標準的 JS Object
@DingDang({ sceneStorage: { set: (k, v) => sessionStorage.setItem(k, JSON.stringify(v)), get: (k) => JSON.parse(sessionStorage.getItem(k)), del: (k) => sessionStorage.removeItem(k) } }) class App extends React.Component { render() { return (認識一個完整的Store) } } render( , document.querySelector("#app") )
const store = { namespace: "demoStore", state: {}, rules: {}, reducer: {}, effect: {}, initialization: () => false, destroy: () => false }
事實上,store中只有namespace字段是必須的,其他的字段如果你不需要的話,可以不寫。namespace(命名空間)
該屬性的值是一個字符串 , 在dingDang中請務必保證namespace的唯一性,因為我們需要以此為依據去判定用戶是否進入了一個全新的場景。state (狀態機)
該屬性中主要用來存儲store中的所有數據集 , 一般來說dingDang會將這里的數據都轉換為immutable類型。rules (規則)
首先讓我們來看一個完整的rules的案例:
export default { namespace: "demoStore", state: { name: "張三" }, rules: { name: [ { validate: (state, name) => name ? true : false, error: "用戶姓名不能為空", miss:false }, { validate: (state, name) => name.length < 6, error: "用戶姓名最大長度不能超過6!", miss:true } ] } }
rules 中配置的其實是針對state 中數據的校驗機制 ,比如在我們的state 中有name這個字段 , 那么你可以在 rules中也配置一個 對應的name字段 , 但是在rules中 , 該字段的值必須為數組, 具體的校驗規則,我們會按照數據的先后順序來執行。 數據中存儲的是每一個 獨立的 rule ,一個標準的 rule如下:
{ validate: (state, name) => name ? true : false, error: "用戶姓名不能為空", miss:false }
validate : 值為一個判斷函數 , 該函數我們會自動的注入全量的state參數, 以及你即將賦予字段的新值 , 例如:name 。 這里的校驗邏輯為: 如果滿足你所需的格式 ,那么返回true , 否則false error: 錯誤提示 , 在執行validate得到false之后拋出的異常信息 miss : 定義是否丟失, 這里的含義是指, 如果即將賦予的新值不能滿足校驗條件, 那么新的值是否丟失掉(即不存儲進state) 如不定義該字段, 那么該字段默認為false , 即不丟失 ,依然賦予state。reducer (折疊器)
該字段內存儲的應該都是純函數 ,在這里你可以直接去針對state賦予全新的值 , 首先讓我們來看一段相對完整的reducer代碼案例:
export default { namespace: "orderStore", state: { goodsList: [ { id: 1, name: "方便面", price: 2 }, { id: 2, name: "筆記本電腦", price: 3281 } ], cart: [] } reducer: { addToCart: (state, goods) => { return state.set("cart", state.get("cart").push(goods)); } } }
正如上面的demo所示 , 我們會為reducer 中的每一個函數的 第一個參數都注入一個全量的 immutable 類型的state , 而第二個參數則是你在調用的時候傳入的。我們對reducer的要求是,最后你必須返回一個你期望的、全新的、全量的state。 下面我們看一段調用reducer 的案例代碼:
@Page(Store) export default class GoodsList extends React.Component { static injectProps = { goodsList: [], cart: [] } _addToCart = async (n) => { const {execReducer} = this.props; try { await execReducer("addToCart")(n) } catch (err) { console.log(err) } } render() { const {injectProps: {goodsList}} = this.props; return () } } |
this._addToCart(n) }>加入購物車 }/> |
上述的demo中 , 我們希望你不要被過多的去關注可能對于你來說未知的代碼影響,你只需要關注我們希望闡述的內容即可(即_addToCart函數), 首先我們應該明確_addToCart函數是一段調用reducer的代碼 , 其次我們觀察到 , _addToCart函數采用了async await 的方式來書寫, 說明該函數是異步的 , 并且返回了一個Promise對象給我們 。 事實上,在你執行reducer時,dingDang內部有可能會去rules中取到對應的規則進行校驗,如果出現異常的話會reject出來給你 , 所以這里 catch到的err其實是你的rules中所配置的信息 , 同時如果你的reducer沒有任何毛病, dingDang依然會有返回值給你,這個返回值是reducer 之后的一個全新的state。effect (副作用的)
我們將這里定義為副作用的 , 也就是希望你將所有的非純函數在這里定義(依賴于外部因素的函數,相同輸入并非能保障得到相同的結果 ,比如調用API)。 慣例,讓我們看一段完整的effect案例:
export default { namespace: "orderStore", state: { goodsList: [], cart: [] } reducer: { addToCart: (state, goods) => { return state.set("cart", state.get("cart").push(goods)); } }, effect:{ queryGoodsList: async ({resolve , reject , state , execReducer , onChangeState} , params) => { const result = await queryGoodsListByAPI(params); if( result.success ){ await onChangeState(result.goodsList).catch(err => reject(err)); resolve(true) }else { reject( result.error ) } } } }
effect 的參數,我們注入的比較多, resolve 、 reject 這里就不作解釋了 , 如果你不是很清楚, 建議去溫習一下Promise 。state 也不作過多的解釋了。 這里我們稍微來提一下 execReducer 和 onChangeState 這兩個函數 。 execReducer 在前面我們也見過 , 這個函數屬于dingDang的系統級函數,主要用來 輔助你去調用reducer。 onChangeState 也是一個dingDang系統級函數 , 這個函數是便于你直接去修改state中的數據 。 我們注意區分一下reducer 和 onChangeState 的區別 , 一般來說reducer的調用方式如下:
execReducer("addToCart")(params);
而onChangeState的調用方式
onChangeState(jsObjectParams)
我們總結概括一下,reducer其實是你用來去調用你自己聲明的指定的一個reducer函數 , 而onChangeState 其實是直接去修改的state中的值 。 一般來說, 如果你無需做業務邏輯, 僅僅只是想把一個數據放進state , 我們推薦你使用 onChangeState 的方式, 請不要擔心rules 的校驗問題 onChangeState 依然 會去執行rules的校驗代碼 , 而如果您不僅僅是將一個數據放進state , 在這中間可能還有很多業務邏輯代碼, 那么我們推薦你自己去寫一個reducer , 然后使用 execReducer 來進行調用initialization (store生命周期中的初始化)
initialization 是一個初始化函數 , 這里不想過多的說什么 , 主要重點說一下 , 我們為這個函數注入了 execReducer 、 execEffect 、 onChangeStatedestroy (store生命周期中的銷毀)
與initialization同理 , 注入的參數也相同系統級函數介紹 execReducer
高階函數 , 主要用來調用 reducer , 返回PromiseexecEffect
高階函數 , 主要用來調用 effect , 返回PromiseonChangeState
簡化修改state中值的方式Page 裝飾器
用來裝飾一個頁面的入口 ,裝飾之后的頁面 可以使用聲明式注入 demo案例如下
@Page(store) class Home extends React.Component { static injectProps = { initName: null, name: null } render() { const {injectProps: {initName, name}, onChangeState} = this.props; return (Component裝飾器) } }{initName}
{name}
用來裝飾一個頁面下的子組件,裝飾之后的頁面 可以使用聲明式注入 demo案例如下
@Component class Card extends React.Component { constructor(props) { super(props) this.state = { error: "" } } static injectProps = { name: null } render() { const {injectProps: {name}} = this.props; return (injectProps (聲明式注入){name}{this.state.error}) } _onChangeName = () => { const {onChangeState} = this.props; onChangeState({name: "李四李四李四李四李四李四"}).catch(e => this.setState({error: e})) } }
在組件中使用 static injectProps 的方式可以來聲明 讓dingDang 從store中為你注入哪些數據。ScenePage (場景頁面)
在某些業務背景下,我們可能需要多個頁面來完整一組業務。 假設我們需要 A B C 3個頁面來完成一組業務 , 在這組業務中 數據其實基本上是相同的, 針對數據的某些業務操作也是相同的。 在這種背景下,我們提出了場景的概念。 我們對場景的定義:多個頁面之間針對同一組業務數據進行的一連串行為動作來完成的一組業務,我們稱之為場景。 普通的Page裝飾器裝飾之后的頁面只能取自己獨立的那份store , 而使用ScenePage裝飾之后的多個頁面 , 只要綁定的Store 的namespace相同,那么這個Store的聲明周期將一直存在,直到用戶跳出當前場景。使用
npm install 0.1.1-alpha --save
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83636.html
摘要:所以前端工程師不僅僅是寫好頁面和做好兼容性。對前端工程師的技術能力也會帶來考驗。這里想要說的是,如果使用了,使用了服務端渲染,對于前端工程師的個人素質要求會比較高,因為需要處理很多服務端的問題。 背景 我們團隊有個項目由于開發時間較長,且是前后端雜糅的開發方式,維護成本很高,在線上暴露的問題很多。而且因為對接了公司一百多條產品線,每天都會接到大量的客訴和產品線反饋的問題。2017年11...
摘要:擴展單一職責原則又稱單一功能原則,面向對象五個基本原則之一。馬丁表示此原則是基于湯姆狄馬克和的著作中的內聚性原則發展出的。 [解讀]Thinking in React 原文:http://facebook.github.io/react/docs/thinking-in-react.html 前言 Thought is the seed of action 這是放置在官方的QUICK ...
摘要:引言組件中有很多彈出式組件,常見的如,以及等。這樣一種層次結構在實踐中大大降低了各類彈層組件的實現和維護成本。但是的組件實現了一個大多數組件庫都沒有實現的功能彈層的嵌套處理。 引言 UI 組件中有很多彈出式組件,常見的如 Dialog,Tooltip 以及 Select 等。這些組件都有一個特點,它們的彈出層通常不是渲染在當前的 DOM 樹中,而是直接插入在 body (或者其它類似的...
摘要:雅虎從很早就開始招聘和培養研究型人才,雅虎研究院就是在這個過程中應運而生的。今天我就來說一說雅虎研究院的歷史,以及過去十多年間取得的成就,聊一聊如何通過引進高級人才,迅速構建起一支世界級的研發團隊。 showImg(https://segmentfault.com/img/remote/1460000013995512); 作者:王下邀月熊 編輯:徐川 前端每周清單專注大前端領域內容,...
閱讀 3717·2021-10-11 10:59
閱讀 1301·2019-08-30 15:44
閱讀 3479·2019-08-29 16:39
閱讀 2888·2019-08-29 16:29
閱讀 1800·2019-08-29 15:24
閱讀 808·2019-08-29 15:05
閱讀 1264·2019-08-29 12:34
閱讀 2302·2019-08-29 12:19