(應用)企業後臺系統敏捷開發-dva

什麼是dva

dva 是一個基於 redux 和 redux-saga 的數據流方案.前端

爲何使用dva

由於它簡化了react引入redux的過程。java

傳統redux與dva對比

redux:react

clipboard.png

開發時,咱們須要action,reducer等文件,而且須要自行分類,不太清晰。webpack

dva:web

clipboard.png

開發時,把 store 及 saga 統一爲一個 model 的概念, 寫在一個 js 文件裏面,分類清晰。
增長了一個 Subscriptions, 用於收集其餘來源的 action。redux

如何使用dva

函數式組件與非函數式組件

概要

HelloWorldModel.js服務器

export default {
  namespace: 'HelloWorldModel',
  state: {str:"hi"},
  reducers: {
    
  },
};

這是react組件的建立:react-router

class HelloWorld extends Component {
  constructor() {
    super()
    this.state = {  }
  }

  sayHi () {
    alert('this.props.HelloWorldModel.str)
  }

  render () {
    return (
      <div onClick={this.sayHi.bind(this)}>Hello World</div>
    )
  }
}

export default connect(({ HelloWorldModel }) => ({
  HelloWorldModel,
}))(HelloWorld);

函數式組件app

const HelloWorld = (props) => {
  const sayHi = (event) => alert(this.props.HelloWorldModel.str)
  return (
    <div onClick={sayHi}>Hello World</div>
  )
}
export default connect(({ HelloWorldModel }) => ({
  HelloWorldModel,
}))(HelloWorld);

屬性與狀態

頁面的數據分爲2大類:
1.頁面屬性:Modal打開或者關閉,與用戶行爲相關,與後臺數據無關
2.頁面狀態:Table展現的數據內容,與用戶行爲無關,與後臺數據相關
我一般在react組件中直接使用state做爲頁面屬性,將頁面狀態存在model中,
而函數式組件,則將頁面屬性和狀態所有存放在model中。dom

生命週期

上面是react組件和函數式組件的寫法區別,
經過react組件寫法聲明的組件繼承了「react.Component」的一些屬性及方法,如生命週期鉤子函數等。
而函數式組件只是個返回dom節點的方法,因此不具有生命週期函數。
由於dva的數據流是單向的,
用戶行爲=》視圖=》model.Effect=>model.Reducer=>store變化=>視圖更新,
react組件能夠在「componentWillReceiveProps」鉤子中決定是否容許當前組件內的數據流動,
函數式組件只能被動接收數據流動。

頁面與狀態的綁定和流轉

如上述代碼,頁面與model的綁定,是經過connect方法實現的,在connect方法中,入參能夠抓取到全部導入的model文件,咱們能夠在每一個組件中(須要關聯model的)「重載」connect方法,只獲取咱們當前頁面所需的model,展現在頁面上。而頁面的事件則可使用dispatch觸發model的Effect事件與服務端交互以後執行reducer,store(model數據)變化後,頁面由於connect了model,至關於訂閱了model的變化,數據流入,頁面更新。

公共狀態抽離

一些公用的狀態是能夠抽離到同一個model中的,如登陸態,上一次查詢參數等。

實際應用中的一些解決方案

動態組件

dva提供dynamic方法支持動態加載組件和model,

import dynamic from 'dva/dynamic';

const UserPageComponent = dynamic({
  app,
  models: () => [
    import('./models/users'),
  ],
  component: () => import('./routes/UserPage'),
});

經過動態加載後,build出來的文件將index.js切割成index.js(體積變小) + 1.async.js等等,
可是index.js默認是經過"./"來加載1.async.js的,對於前端靜態資源與服務端應用不在同一臺服務器的狀況,如
java boot應用 發佈在http://xxx.com/a =》 a.ftl 中引用 dva build以後的靜態資源,而靜態資源發佈倒是在另外一臺服務器上http://zzz.com/dvaBuild/dist,
index.js仍是去訪問默認的"./1.async.js" 其實訪問的是http://xxx.com/a/1.async.js,...
能夠直接在頁面script標籤中,

window.__webpack_public_path__ = 'http://zzz.com/dvaBuild/dist';

路由跳轉

權限判斷(接入第三方登錄)

1.是否登錄
在GlobalModel中保存着登陸態,路由中使用AuthComponent替換Route,在渲染路由組件的時候就會判斷是否登錄,若是沒有登錄渲染正在登錄loading頁面,等待第三方登錄接口判斷已經登錄,頁面會自動更新爲路由組件。
這是第三方登錄,若是是內部登錄使用react-router跳轉。
AuthComponent

@connect(({GlobalModel}) => GlobalModel)
export default class AuthComponent extends PureComponent {
  render() {
    const { component: Component, isLogin, ...rest } = this.props;
    return  (
      <Route
      {...rest}
      render={props =>
        isLogin == 1 ? (
          <Component {...props}/>
        ) : (
          <Logining></Logining>
        )
      }
    />
    )
  }
}

GlobalModel

effects: {
    *CheckLogin({payload,callback}, {call,select,put}) {
        const loginfoResult = yield call(getLoginInfo);
        if(loginfoResult && loginfoResult.ResponseStatus && loginfoResult.ResponseStatus.Ack == "Success" && loginfoResult.userBasicInfoDTO){
          if(loginfoResult.userBasicInfoDTO && loginfoResult.userBasicInfoDTO.userAccount && checkPermission(loginfoResult.userBasicInfoDTO.userAccount)){
            yield put({type:"save",loginInfo:loginfoResult})
            callback();
          }else{
            yield put( routerRedux.push('/NoPermission') ); //沒有權限
          }
        }else{
          window.location.href = getLoginUrl();
        }
    },

須要在各個路由頁面綁定的model的路由切換訂閱方法中作登錄判斷,
頁面切換就要判斷是否登錄或鑑權

subscriptions: {
    setup({ dispatch, history }) {  // eslint-disable-line
      return history.listen((location) => {
        dispatch({
          type: "GlobalModel/onShow",
          callback: () => {

                dispatch({type:"BaseInfoQuery",payload:{}});
            }

            })
      })

    },
相關文章
相關標籤/搜索