咱們將dingDang定義爲一個React數據層產品,由於在dingDang設計之初,咱們就抱着用戶的開發體驗放在第一位的理念。 咱們但願在簡單的業務場景下,你能夠儘量的用直截了當的方式來寫代碼,而不是去建一大堆的JS文件,而當你的業務逐漸 的複雜的時候,你又能夠在你簡單的代碼上很輕鬆的進行擴張、模塊化。 起初,咱們是很認同Redux的全局Store的概念的,可是當咱們的項目成長到必定規模時,咱們發現整個研發團隊對於成員的 職業素質要求很高,不然將會寫出很糟糕的代碼,致使整個Store混亂不堪,這無形之中增長的研發團隊的成本。 經過咱們自身的項目總結,咱們發如今大多數的業務場景下,其實咱們須要的是即用即開、用完即毀的Store 。 同時在少數狀況下,咱們會遭遇到多個頁面之間共享一部分數據的狀況,咱們將這種狀況稱之爲場景,也就是咱們下面將要描 述的數據場景化概念,這與Redux的全局Store在抽象的層面上是徹底不一樣的概念,在代碼層面上則是粒度大小的區別。
dingDang自己並不具有多少能力,咱們只定義的數據流動的溝壑,以及在這些溝壑中設立了多個崗哨,咱們將這些崗哨對外開 放,你能夠在崗哨上作些什麼,通俗一點也就是插件機制。 咱們默認提供了兩個插件:
injector(注射器):javascript
主要定義了對頁面或組件的props注入規則,值得注意的是,該插件是必須的,不然dingDang幾乎什麼也幹不了。
rules(規則):java
該插件主要針對store中的state數據提供一些數據校驗機制 , 或者在表單場景下比較適用。
咱們對數據場景化的定義是: 用戶在執行某一個徹底的業務行爲時,須要在多個頁面之間來回切換 ,而且在多個頁面中 都是針對同一份業務數據進行操做。那麼咱們將這多個頁面稱之爲:【場景】。而多個頁面共享數據這種行爲稱之爲:【數據場景化】 在實際落地的時候,數據場景化每每會由於用戶的操做習慣、dingDang的應用平臺等出現各式各樣的問題。 例如:按照咱們定義的數據場景化的狀況下,若是用戶在一個由5個頁面組成的場景中進行某些行爲動做,當用戶已經進行到最後一個 頁面時,忽然點擊了瀏覽器的刷新,那麼可能會將前4個頁面的全部數據丟失,也就是說咱們的場景須要一個持久化的過程。 在最初,咱們試想着將數據相對持久化在瀏覽器的sessionStorage中,可是隨即咱們發現,這樣咱們將會拋棄了react-native這個玩意, 因此乾脆咱們就將數據持久化的過程交與你來完成,根據你的實際業務場景選出適合本身的持久化方案。 目前,咱們僅僅只支持在全局配置一套持久化方案,咱們深知這是以爲不能知足某些業務需求的,在稍後的版本中,咱們會提供針對Store級別 配置獨立的持久化方案,若是Store中沒有配置持久化方案,那麼默認採用全局的持久化方案。
最簡化單頁面Store操做react
數據場景化demogithub
每個Store中都存儲了頁面相關的狀態(state)、用戶的行爲動做(reducer、effect)、以及第三方插件補充的部分機制(例官 方插件:rules),Store能夠被裝飾器進行裝飾,裝飾以後的Store能夠被渲染到頁面上、也能夠被多個頁面共享。
每個Store都必須具有該字段 , 該字段標示Store的惟一性。
每個Store都必須具有該字段 , 該字段用來存儲頁面所需的狀態信息(也就是數據)
reducer內建議都寫純函數,避免第三方的不可靠元素 , reducer 是惟一能夠直接去修改state的入口,每個reducer 最終都必須返回一個全新的state , 固然,你返回的state 並不必定就是最終頁面上所體現出來的 , 由於當你的state 返回出去以後還有可能被一部分攔截器進行攔截,對你的數據進行修改, 因此請留意本身所配的插件信息。
effect爲反作用函數彙集地 , 通常來講, 與服務端進行ajax交互的代碼咱們都適應於寫在這裏,effect內沒法直接對state進行修改 , 不過咱們提供了 調用reducer 的函數 ,也便是說在effect中若是你想修改state , 那麼你應該經過reducer進行中轉。
此函數爲高階函數 ,咱們會在頁面級的props 以及每個effect中注入這個執行器,以便你能夠對state進行某些操做。 每個reducer都會返回一個Promise對象 ,若是Promise處於resolve的狀態的話,那麼咱們會返回最新的全量的state, 不然咱們會拋出異常! 調用方式以下:
execReducer('reducerName')(payload)
此函數爲高階函數 ,咱們會在頁面級的props 以便你能夠在頁面中方便的調用effect 每個effect都會返回一個Promise對象,在每個effect中咱們都將resolve、reject暴露出來,以便你控制你本身的業務邏輯。 調用方式以下:
execEffect('effectName')(payload)
該函數是咱們貼心的爲你提供的直接修改state的函數, 上文中咱們提到過,store中的reducer是非必要的,那麼在沒有reducer 的狀況下咱們怎麼修改 state 呢? 這個時候就可使用由系統提供的onChangeState , 實際上在dingDang的內部,即便你沒有寫reducer ,咱們也會動態的生成一個,而且 默認狀況下咱們會爲reducer掛載一個名稱爲:[onChangeState${random}]的函數,而這個函數通過咱們的轉換,就是你看到的onChangeState函數了, 咱們會在頁面級的props以及effect中爲你注入這個函數。 調用方式以下:
onChangeState({name:'張三'})
當業務場景僅僅侷限於單頁面時使用。
場景裝飾器,當使用該裝飾器時,多個頁面若是採用的namespace相同的store,而且是連續相互之間跳轉,那麼會共享store,被認爲是一個場景。
被裝飾者被標示爲一個組件(非頁面級入口),使用該裝飾器的話,那麼該組件必須被一個 Page裝飾器說裝飾的頁面使用, 不然會報錯。
在這裏咱們暫時不開放插件的相關攔截點,主要介紹一下官方目前提供的兩個插件。
該插件主要用來協助裝飾器將Store注入進view中,你只須要知道沒有這個插件,你的dingDang將沒法正常運行起來便可,因此該插件是必要配置的,固然, 若是你本身實現了一套注射器,那麼你能夠將此插件替換掉。
該插件主要定義了state中每個字段的校驗規則 , 具體的校驗過程在 每一次執行完reducer以後進行校驗。 先看一個demo。
const store = { namespace:'demoStore' , state:{ name:'' }, rules:{ name:[ { validate:(state , name) => name.length < 8, error:'用戶名的長度不能大於8', merge:true } ] } }
rules中的每個key都要與state一一對應,以便插件識別是校驗哪個字段。
validate(必要) 校驗函數ajax
error(必要) 錯誤提示npm
merge(非必要,存在默認值) 若是發生了錯誤,是否依然合併進state , 該字段默認爲truereact-native
npm install 0.2.4-alpha --save