基於react+redux的輕量級架構dva初使用及應用邏輯分析

來源:互聯網
上載者:User

隨著React的大火,flux架構也跟著火了起來,Redux是實現flux架構的庫中的佼佼者,使用react+redux來開發應用的開發人員也越來越多

確實,React+Redux+webpack+babel+es6,這是一個極具生產力的組合

源自flux架構的單向流動使得應用的邏輯和資料流動變得可控,當應用邏輯變得複雜的時候,其優勢越加明顯,開發越加高效

但是在開發的時候出現了一些問題,比如說概念太多,檔案太鬆散等等問題

以及為瞭解決非同步互動問題,會引用一些中介軟體來處理store,比較常見的是用thunk中介軟體+asysc或者用saga等等

圖為一個中介軟體處理store的代碼

這不是Dva解決的最大的問題,Dva的重點是引進了model這個概念,將以前一堆鬆散的概念和檔案組織到一起了,這才是關鍵

React+redux+redux-saga中,每新增1個組件或者說新增1個頁面,都要新增3個檔案,sagas,reducers,action各自對應1個檔案,編寫的時候不停的切換,極其的麻煩,而且檔案多了之後,檔案的管理不是很方便

DVA正是解決這些問題的

首先,我想說一個問題,那就是……Dva這個名字……

咳,好吧,最初的最初我關注到這個架構,就是因為它的名字,然後就好奇的點進去了,然後就被它的優雅給吸引,再也不可自拔……

然後它的設定檔,叫roadhog

如果你是一名OWer,那麼你已經想迫不及待的看下去了

為什麼要用DVA呢。

以下是官方文檔的說明:

易學易用:僅有 6 個 api,對 redux 使用者尤其友好

elm 概念:通過 reducers, effects 和 subscriptions 組織 model

支援 mobile 和 react-native:跨平台

支援 HMR:目前基於 babel-plugin-dva-hmr 支援 components、routes 和 models 的 HMR

動態載入 Model 和路由:按需載入加快訪問速度

外掛程式機制:比如 dva-loading 可以自動處理 loading 狀態,不用一遍遍地寫 showLoading 和 hideLoading

完善的文法分析庫 dva-ast:dva-cli 基於此實現了智能建立 model, router 等

支援 TypeScript:通過 d.ts

Let’s start!

首先奉上Dva官方文檔地址,是發布在github上的:dva

首先是安裝:

使用npm安裝即可: npm install dva-cli@0.7 -g

需要注意的是:1.node版本必須在6.5以上 2.dva-cli必須版本在0.7.x(可以安裝完dva-cli之後用dva -v查看一下版本號碼)

以上兩點都是DVA官方的要求

然後使用new命令建立一個新的dva應用: dva new dva-demo

耐心等待建立完成

這是應用建立成功的提示

好的,現在我們來看建立好的工程~

可以先運行一下試試: npm run start

運行結果如圖

url為:http://localhost:8000/#/?_k=gebc0m

嗯 一個奇怪的url

不過如果你對前端路由,或者說對react-router有所瞭解的話,就知道這是hashHistory

如果不習慣可以修改為browserHistory

在根目錄下的index.js檔案中

修改代碼

再運行看看效果

url正常了

不過路由改成browserHistory的話,還需要後端代碼的配合

現在我們來觀察這個建立好的工程的目錄

可以很明顯的看到代碼都放在src檔案夾了

另外在public檔案夾下放了一個index.html檔案

我們開啟它來看看

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1">  <title>Dva Demo</title>  <link rel="stylesheet" href="/index.css" /></head><body><div id="root"></div><script src="/index.js"></script></body></html>

很明顯,這是一個React典型應用的html模版檔案,和用create-react-app腳手架建立的應用中產生的index.html內容差不多

我們幾乎不對這個html進行代碼改動,也不在裡面加入html標籤,css檔案等,整個檔案的重點只是body裡的兩行代碼

<div id="root"></div>

這是確定了id的div標籤,我們編寫的React組件最後都是展示在這個div塊裡

<script src="/index.js"></script>

最後所有js檔案都會打包到這個Js檔案裡統一載入

再來看js檔案

整個程式的入口檔案是根目錄下的index.js檔案

import dva from 'dva';import { browserHistory } from 'dva/router';import './index.css';// 1. Initializeconst app = dva({  history: browserHistory,});// 2. Plugins// app.use({});// 3. Modelapp.model(require('./models/example'));// 4. Routerapp.router(require('./router'));// 5. Startapp.start('#root');

dva-cli產生的檔案給我們寫的注釋已經寫的很清楚了

先初始化,再載入外掛程式,再載入Model,再載入路由,最後啟動程式

我們就根據這個過程來理清楚檔案關係

先從第4步路由來分析

載入路由的語句為: app.router(require('./router'));

很明顯能看出,載入的是同在根目錄下的router.js檔案

我們開啟router.js檔案

import React from 'react';import { Router, Route } from 'dva/router';import IndexPage from './routes/IndexPage';function RouterConfig({ history }) {  return (    <Router history={history}>      <Route path="/" component={IndexPage} />    </Router>  );}export default RouterConfig;

可以很明顯的看出,主體結構是配置react-router,攔截”/”,然後渲染IndexPage

根據import語句,找到routes目錄下面的IndexPage.js

import React from 'react';import { connect } from 'dva';import styles from './IndexPage.css';function IndexPage() {  return (    <div className={styles.normal}>      <h1 className={styles.title}>Yay! Welcome to dva!</h1>      <div className={styles.welcome} />      <ul className={styles.list}>        <li>To get started, edit <code>src/index.js</code> and save to reload.</li>        <li><a href="https://github.com/dvajs/dva-docs/blob/master/v1/en-us/getting-started.md">Getting Started</a></li>      </ul>    </div>  );}IndexPage.propTypes = {};export default connect()(IndexPage);

顯然,這是一個React組件,而且是Redux中所說的容器型的組件,因為在匯出的時候通過connect這個高階函數來裝飾這個組件,以便能夠從Redux狀態樹中擷取資料

因為這是一個很簡單的頁面,並沒有匯入在Components目錄下封裝好的組件,如果是在實際開發,頁面足夠複雜的時候,會在Component中封裝組件,然後在Routes目錄下的中的組件匯入,然後再匯入路由檔案中

components目錄下的example.js

import React from 'react';const Example = () => {  return (    <div>      Example    </div>  );};Example.propTypes = {};export default Example;

只是1個樣本檔案,沒有使用它,它本身也沒什麼意義

我們再回到根目錄下的index.js中,第4步路由部分載入的檔案我們已經回溯到底了,我們來看第3步model

app.model(require('./models/example'));

可以看出,載入的是models目錄下的example.js檔案

開啟查看其代碼

export default {  namespace: 'example',  state: {},  subscriptions: {    setup({ dispatch, history }) {  // eslint-disable-line    },  },  effects: {    *fetch({ payload }, { call, put }) {  // eslint-disable-line      yield put({ type: 'save' });    },  },  reducers: {    save(state, action) {      return { ...state, ...action.payload };    },  },};

model這個概念,是dva的核心,可以看到上面代碼中主要分為幾個欄位:namespace,state,subscriptions,effects,reducers

這幾個欄位,官方文檔中給出的說明是這樣的:

namespace - 對應 reducer 在 combine 到 rootReducer 時的 key 值

state - 對應 reducer 的 initialState

subscription - elm@0.17 的新概念,在 dom ready 後執行

effects - 對應 saga,並簡化了使用

reducers- 還是對應原來的reducer,概念沒有變化

熟悉react,redux, redux-saga 這一套應用架構的,無縫切換

可以看到,關於redux中action,reducer的那一堆,都集中在model裡面了,編寫代碼再也不用切換過去切換過來,而且在一個檔案中,組織代碼非常方便,再也不用code everywhere

services目錄下的檔案是為models目錄下的檔案服務的

更多的,可以去看官方給出的一個CURD使用者管理的demo

12 步 30 分鐘,完成使用者管理的 CURD 應用

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.