1. 程式人生 > 其它 >Dva 初讀文件學習

Dva 初讀文件學習

技術標籤:前端面試系列javascriptreact

基於Redux-saga的資料管理方案,Redux-Saga 詳見文章《Redux中介軟體之redux-saga》

1、資料流向

image.png

概念:資料的改變通常是由於使用者互動行為或者瀏覽器行為觸發的,利用dispatch發起action(操作),然後通過一系列改變state

(1)同步:通過Reducer直接改變state

(2)非同步:先觸發Effects,然後流向Reducer,然後由Reducer最終改變state

2、Models

(1)State--資料狀態

State表示Model的狀態資料,通常為一個JavaScript物件

const app = dva();
console.log(app._store); // 頂部的 state 資料

(2)Action--改變state的唯一途徑

action是一個普通js物件,是改變state的唯一途徑,通過dispatch呼叫一個action,從而改變對應的state資料。action必須帶有type、其他引數自定義。要發起一個action必須要通過dispatch進行呼叫。

**注意:dispatch是要在元件connectModel之後,通過props傳入的,**

dispatch({
  type: 'add',
});

dispatch內的物件就是一個action

(3)dispatch函式--實現action的方法

dispatch函式是用於觸發action(實現action)物件的一個函式,action是改變state的唯一途徑,但是action只是描述了這個行為,真正需要dispatch來觸發這個行為。

dva裡面,元件connect Model後就可以利用props訪問dispatch,然後dispatch就又可以呼叫Model裡面的Effects然後呼叫Reducer或者直接呼叫Reducer改變state的狀態

dispatch({
  type: 'user/add',
  payload:{}
})

(4)Reducer--描述和具體實現資料改變

Reducer函式接受兩個引數,之前已經累積運算的結果和當前要被累積的值,返回一個新的結果(兩個引數:當前值,和操作)

在Dva裡面,第一個引數聚合累積的結果就是當前model的state,通過action傳入的值,和當前reducer裡面的值進行運算,返回新的state。Reducer必須是純函式,同樣的輸入,輸出值必然一樣。

 reducers: {
        // reducer執行函式
        'delete' ( state, { payload: id } ) { 
            // 返回陣列state裡面不等於傳入id的值,構建一個新陣列,可以實現刪除傳入id這項
            return state.filter(item => item.id !== id)
        }
    }

(5)Effect

Action 處理器,處理非同步動作,基於 Redux-saga 實現。Effect 指的是副作用。根據函數語言程式設計,計算以外的操作都屬於 Effect,典型的就是 I/O 操作、資料庫讀寫。

dva 為了控制副作用的操作,底層引入了redux-sagas做非同步流程控制,由於採用了generator的相關概念,所以將非同步轉成同步寫法,從而將effects轉為純函式。

   effects: {
      *fetchFront ( { payload }, { call, put } ) {
         const response = yield call( query, 'frontservice', { query: frontQuery, variables: payload.variables } );
         yield put({
        type: 'saveFront',
        payload: response.data,  
         });
      }
  },

yield:標識每一步的操作

call:執行非同步函式

put:發出Action,使用put(類似於dispatch),操作reducer,改變state

(6)Subscription

Subscription是一種從源獲取資料的方法,來自於elm

Subscription語義是訂閱,用於訂閱一個數據源,然後根據相應的條件dispatch需要的action。資料來源可以是當前的時間、伺服器的 websocket 連線、keyboard 輸入、geolocation 變化、history 路由變化等等

import key from 'keymaster';
...
app.model({
  namespace: 'count',
  subscriptions: {
    keyEvent({dispatch}) {
      key('⌘+up, ctrl+up', () => { dispatch({type:'add'}) });
    },
  }
});

(*)例項

下面是一個完整的Model的例子

export default {

  namespace: 'example',

  state: {},

  subscriptions: {
    setup({ dispatch, history }) {  // eslint-disable-line
    },
  },

  effects: {
    *fetch({ payload }, { call, put }) {  // eslint-disable-line
      //非同步操作
      yield call({delay,1000})
      //發出Action
      yield put({ type: 'save' });
    },
  },

  reducers: {
    save(state, action) {
      return { ...state, ...action.payload };
    },
  },

};

3、Router

這裡的路由指的是前端路由,spa應用裡面,需要由前端程式碼控制路由邏輯,控制路由相關操作

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
//引入component
import IndexPage from './routes/IndexPage';
import Products from './routes/Product'

function RouterConfig({ history }) {
  return (
    <Router history={history}>
      <Switch>
        <Route path="/" exact component={ IndexPage } />
        <Route path="/products" exact component={ Products}/>
      </Switch>
    </Router>
  );
}

export default RouterConfig;

dva提供了router來控制路由,使用react-router

4、Router Components

在 dva 中,通常需要 connect Model的元件都是 Route Components,組織在/routes/目錄下,作為頁面元件;

而/components/目錄下則是純元件(Presentational Components),一般作為通用元件

  • roadhog

文件地址:https://github.com/sorrycc/roadhog

Roadhog是一個包含dev,build和test的命令列工具,基於react-dev-utils,可以理解為可配置版的create-react-app。

  • propTypes

使用propTypes進行型別檢查,驗證和確保元件接受到的props是有效的資料型別,當傳入的 prop 值型別不正確時,JavaScript 控制檯將會顯示警告。出於效能方面的考慮,propTypes 僅在開發模式下進行檢查。

import React from "react";

import PropTypes from "prop-types";

// 純函式元件寫法(傳入刪除和列表陣列pros)
class ProductList extends React.Component{
  render(){
    ...
  }
}

// propTypes檢查
ProductList.propTypes = {
  //檢查資料型別並且是必須的
  onDelete: PropTypes.func.isRequired,
  products: PropTypes.array.isRequired
};

export default ProductList;