<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # dva [dva](https://github.com/dvajs/dva) 首先是一個基于現有應用架構 [redux](https://github.com/reduxjs/redux) 和 [redux-saga](https://github.com/redux-saga/redux-saga) 的數據流方案,然后為了簡化開發體驗,dva 還額外內置了 [react-router](https://github.com/ReactTraining/react-router) 和 [fetch](https://github.com/github/fetch) ,所以也可以理解為一個輕量級的應用框架,沒有引入任何新概念。 1. 腳手架工具:[dva-cli](https://github.com/dvajs/dva-cli) 2. [dva-知識地圖](https://github.com/dvajs/dva-knowledgemap/blob/29549f253ad130802146b6d066b3ad1af4c7d0be/README.md) ## 整體架構 分析一下這個圖: ![](https://img.kancloud.cn/2a/90/2a909b4e546464d7bef2a296873fdf7e_1614x508.png) 首先我們根據 `url` 訪問相關的 `Route-Component`,在組件中我們通過 `dispatch` 發送 `action` 到 `model` 里面的 `effect` 或者直接 `Reducer`; 當我們將`action`發送給`effect`,基本上是取服務器上面請求數據的,服務器返回數據之后,`effect` 會發送相應的 `action` 給 `reducer`,由**唯一能操作** `state` 的 `reducer` 產生新的 `state` ,然后通過`connect` 重新渲染組件。 當我們將`action`發送給`reducer`,那直接由 `reducer` 產生新的 `state`,然后通過 `connect` 重新渲染組件。 這樣我們就能走完一個流程了。 ## Model `model` 是 `dva` 中最重要的概念,`Model` 非 `MVC` 中的 `M`,而是領域模型,用于把數據相關的邏輯聚合到一起,幾乎所有的數據,邏輯都在這里進行處理分發 ### state State 表示 Model 的狀態數據,通常表現為一個 javascript 對象(當然它可以是任何值);操作的時候每次都要當作不可變數據(immutable data)來對待,保證每次都是全新對象,沒有引用關系,這樣才能保證 State 的獨立性,便于測試和追蹤變化。 在 dva 中你可以通過 dva 的實例屬性?`_store`?看到頂部的 state 數據,但是通常你很少會用到: ```js const app = dva(); console.log(app._store); // 頂部的 state 數據 ``` ### namespace `model` 的命名空間,同時也是它在 全局 `state` 上的屬性(作為一個大對象的鍵值),只能用字符串,我們發送在發送 `action` 到相應的 `reducer` 時,就會需要用到 `namespace` 。 ### dispatch 函數 `type dispatch = (a: Action) => Action` dispatching function 是一個用于觸發 action 的函數,action 是改變 State 的唯一途徑,但是它只描述了一個行為,而 dipatch 可以看作是觸發這個行為的方式,而 Reducer 則是描述如何改變數據的。 在 dva 中,`connect`( react-redux 的 connect) Model 的組件通過 props 可以訪問到 dispatch,可以調用 Model 中的 Reducer 或者 Effects,常見的形式如: ```js // 返回 Promise dispatch({ type: 'user/add', // 如果在 model 外調用,需要添加 namespace payload: {}, // 需要傳遞的信息 }); ``` [Dva異步的同步處理](https://www.jianshu.com/p/c11fd2e10f0b) ### reducers 以`key/value` 格式定義 `reducer`,用于處理同步操作,唯一可以修改 `state` 的地方。由 `action` 觸發。其實一個純函數。 在 dva 中,reducers 聚合積累的結果是當前 model 的 state 對象。通過 actions 中傳入的值,與當前 reducers 中的值進行運算獲得新的值(也就是新的 state)。 需要注意的是 Reducer 必須是[純函數](https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md),所以同樣的輸入必然得到同樣的輸出,它們不應該產生任何副作用。 并且,每一次的計算都應該使用[immutable data](https://github.com/MostlyAdequate/mostly-adequate-guide/blob/master/ch3.md#reasonable),這種特性簡單理解就是每次操作都是返回一個全新的數據(獨立,純凈),所以熱重載和時間旅行這些功能才能夠使用。 **如果 reducers中的同步方法名和 effects 中的異步方法名 相同,那么都會被調用,且 優先執行 reducers,應該避免同名!** ### effects 用于處理異步操作和業務邏輯,不直接修改 `state`,簡單的來說,就是獲取從服務端獲取數據,并且發起一個 `action` 交給 `reducer` 的地方。 其中它用到了 redux-saga,里面有幾個常用的函數。 ``` *add(action, { call, put }) { yield call(delay, 1000); // 執行異步函數 yield put({ type: 'minus' }); // 發出一個 Action,類似于 dispatch }, ``` ### subscription Subscriptions 是一種從?源?獲取數據的方法,它來自于 elm。 Subscription 語義是訂閱,用于訂閱一個數據源,然后根據條件 `dispatch` 需要的 action。數據源可以是當前的時間、服務器的 websocket 連接、keyboard 輸入、geolocation 變化、history 路由變化等等。 ```js import key from 'keymaster'; ... app.model({ namespace: 'count', subscriptions: { keyEvent(dispatch) { key('?+up, ctrl+up', () => { dispatch({type:'add'}) }); }, } }); ``` ## Router 這里的路由通常指的是前端路由,由于我們的應用現在通常是單頁應用,所以需要前端代碼來控制路由邏輯,通過瀏覽器提供的?[History API](http://mdn.beonex.com/en/DOM/window.history.html)?可以監聽瀏覽器url的變化,從而控制路由相關操作。 dva 實例提供了 router 方法來控制路由,使用的是 [react-router](https://github.com/reactjs/react-router)。 ```js import { Router, Route } from 'dva/router'; app.router(({history}) => <Router history={history}> <Route path="/" component={HomePage} /> </Router> ); ``` ## Route Components 在[組件設計方法](https://github.com/dvajs/dva-docs/blob/master/v1/zh-cn/tutorial/04-%E7%BB%84%E4%BB%B6%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%B3%95.md)中,我們提到過 Container Components,在 dva 中我們通常將其約束為 Route Components,因為在 dva 中我們通常以頁面維度來設計 Container Components。 所以在 dva 中,通常需要 connect Model的組件都是 Route Components,組織在`/routes/`目錄下,而`/components/`目錄下則是純組件(Presentational Components)。 ## dva-loading 每個頁面中將loading狀態作為屬性傳入組件,在進行樣式處理,比如轉圈圈或者顯示正在加載什么的,但是重點是,我們的app有多個頁面,每個頁面都這么做,很繁瑣。 dva 有一個管理 effects 執行的 hook,并基于此封裝了 [dva-loading 插件](https://github.com/dvajs/dva/tree/master/packages/dva-loading)。通過這個插件,我們可以不必一遍遍地寫`showLoading`和`hideLoading`,當發起請求時,插件會自動設置數據里的 loading 狀態為 true 或 false 。然后我們在渲染 components 時綁定并根據這個數據進行渲染。 `umi-plugin-dva` 默認內置了 dva-loading 插件。 dva-loading的使用非常簡單,在index.js中加入: ``` import createLoading from 'dva-loading'; const app = dva(); app.use(createLoading()); ``` loading 在異步請求發出那一刻會持續監聽該異步請求方法的狀態,在異步請求結束之前 isLoading 的值一直是 true,當此次異步請求結束時 isLoading 的值變成 false,同時 loading 對象停止監聽。 如何只做一次狀態處理,每次請求期間都會觸發loading狀態呢,其實也很簡單啦,因為dva-loading提供了一個global屬性。 ``` loading: { global: true, effects: { 'user/query': true }, models: { 'user/query', true }, } /* 'user/query' 是單一異步請求后臺的方法,在請求過程中,global 和 effects 中值都為 true, 當請求結束,已經有數據返回,userList 中獲取到用戶列表時該值為 false。 可能有個疑問:既然 global 可以展示異步加載是否完成,為什么還要 effects 屬性,這是因為一個頁面中可能同時有多個異步加載,只要有一個異步加載沒有完成,global 都是 true。 */ ``` 如果同時發出若干個異步請求,需求是當所有異步請求都響應才做下一步操作,可以使用`loading.global()`方法,該方法監聽所有異步請求的狀態。 具體參考這個[Commit](https://github.com/umijs/umi-dva-user-dashboard/commit/f81d36c639d35e67db8b2d0a65b561e4af203eb1)。 ## 參考 [dva理論到實踐——幫你掃清dva的知識盲點](https://www.jianshu.com/p/e184cd6d253c) ===好用真舒服,感覺起飛了===
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看