【教程】Pastate.js 響應式 react 框架(七)規模化

這是 Pastate.js 響應式 react state 管理框架系列教程,歡迎關注,持續更新。 javascript

這一章,咱們將介紹 pastate 如何構建大規模應用,以及如何在原生 redux 項目中使用等。前端

路由

當咱們的應用日益複雜時,須要用前端路由的模式來管理多個界面。java

無參數路由

Pastate 應用能夠與通用的 react-router 路由框架配合使用。咱們仍是以 班級信息管理系統 爲例來介紹如何在 pastate 中使用路由,咱們接下來把學生板塊和課程板塊分別放在 /student 和 /class 路由目錄下。react

首先安裝 react-router 的網頁版 react-router-dom:git

$ npm install react-router-dom --save
或
$ yarn add react-router-dom

使用 Router 做爲根容器

接着咱們用路由 Router 組件做爲新的根容器來包裝咱們的原來的根容器 Navigator,代碼以下:
src/index.jsgithub

...
import { BrowserRouter as Router } from 'react-router-dom';

ReactDOM.render(
    makeApp(
        <Router>
            <Navigator.view />
        </Router>,
        storeTree
    ),
    document.getElementById('root')
);

使用 Route 組件來定義路由

接下來,咱們來看看導航模塊 Navigator 的視圖如何修改:
Navigator.view.jsweb

import { Route, Redirect, Switch, withRouter, NavLink } from 'react-router-dom'

class Navigator extends React.PureComponent{
    render(){
        /** @type {initState} */
        const state = this.props.state;

        return (
            <div>
                <div className="nav">
                    <div className="nav-title">班級信息管理系統</div>
                    <div className="nav-bar">
                        <NavLink 
                            className="nav-item"
                            activeClassName="nav-item-active"
                            to="/student"
                        >
                            學生({this.props.count.student})
                        </NavLink>
                        <NavLink 
                            className="nav-item"
                            activeClassName="nav-item-active"
                            to="/class"
                        >
                            課程({this.props.count.class})
                        </NavLink>
                    </div>
                </div>
                <div className="main-panel">
                    <Switch>
                        <Redirect exact from='/' to='/student'/>
                        <Route path="/student" component={StudentPanel.view}/>
                        <Route path="/class" component={ClassPanel.view}/>
                    </Switch>
                </div>
            </div>
        )
    }
}

export default withRouter(makeContainer(Navigator, state => ({...})))

咱們對該文件進行了 3 處修改npm

  • 使用路由組件 Switch + Route 來代替以前手動判斷渲染子模塊的代碼,讓路由自動根據當前 url 選擇對應的子組件來顯示;
  • 使用路由組件 NavLink 來代替以前的導航欄按鈕,把每一個 tab 綁定到一個特定的 url;
  • 使用路由的 withRouter 函數包裝咱們原來生成的 container,這使得當路由變化時,container 會收到通知並從新渲染

完成!這時咱們就能夠看到,當咱們切換導航標籤時,url 和顯示的子組件同時改變:redux

路由生效

當咱們在 /class 路徑下刷新或進入時,應用能夠顯示爲課程板塊,這是路由組件爲咱們提供的一個在原來的無路由模式中沒有的功能。segmentfault

咱們這裏使用的是 BrowserRouter 對應的 browserHistory ,所以在 url 中是不用 HashRouter 的 hashHistory 模式下的 # 分割符來分割前端和後端路由,因此在服務器端須要作一些相關配置,把這些路徑都路由到相同的一個HTML應用。若是後端難以配合修改,你可使用 HashRouter 代替咱們上面的 BrowserRouter:

// index.js
import {  HashRouter as Router } from 'react-router-dom';

這是就會自動啓用 # (hash路由)來分割前端和後端路由:

啓用 code#/code 來分割前端和後端路由

有參數路由

咱們在上面的路由不涉及參數,若是咱們須要使用相似 \student\1\student\2 的方式來表示目前顯示哪個 index 或 id 的學生,咱們能夠在定義路由時使用參數:

// Navigator.view.js
<Route path="/student/:id" component={StudentPanel.view}/>

並在被路由的組件的 view 中這樣獲取參數:

// StudentPanel.view.js
let selected = this.props.match.params.id;

在 actions 中使用路由

若是你要在 actions 中簡單地獲取當前網址的路徑信息,你能夠直接使用 window.location 獲取:

// StudentPanel.model.js
const actions = {
    handleClick(){
        console.log(window.location)
        console.log(window.location.pathname) // 當使用 BrowserRouter 時
        console.log(window.location.hash) // 當使用 HashRouter 時
    }
}

若是你須要在 actions 獲取和更改路由信息,如跳轉頁面等,你能夠在 view 視圖中把 this.props.history 傳入 action, 並經過 history 的 API 獲取並修改路由信息:

// StudentPanel.model.js
const actions = {
    selectStudent(history, index){
        console.log(history)
        history.push(index+'') 
        // history.push('/student/' + index)
        // history.goBack() // or .go(-1)
    }
}

通過基礎的測試,pastate 兼容 react-router 的路由參數、history 等功能,若是你發現問題,請提交 issue 告訴咱們。

若是你對開發調試體驗的要求很是高,要實現 「Keep your state in sync with your router」, 以支持用開發工具來實現高級調試,能夠參考 react-router-redux 把路由功能封裝爲一個只有 store 而沒有 veiw 的 pastate 服務模塊, 並掛載到 storeTree。若是你作了,請提交 issue 告訴咱們。

嵌入 redux 應用

Pastate 內部使用 redux 做爲默認的多模塊引擎,這意味着,你能夠在原生的 redux 項目中使用 pastate 模塊, 只需兩步:

  1. 使用 Pastate 模塊的 store 中提供的 getReduxReducer 獲取該模塊的 redux reducer,並把它掛載到 redux 的 reducerTree 中;
  2. 把 redux 的 store 實例的 dispatch 注入 astate 模塊的 store 的 dispatch 屬性 。
import { createStore, combineReducers } from 'redux';
import { makeApp, combineStores } from 'pastate';
...
import * as StudentPanel from './StudentPanel';
const reducerTree = combineReducers({
    panel1: oldReducer1,
    panel2: oldReducer2,
    panel3: StudentPanel.store.getReduxReducer() // 1. 獲取 Pastate 模塊的 reducer 並掛載到你想要的位置
})

let reduxStore = createStore(reducerTree)
StudentPanel.store.dispatch = reduxStore.dispatch // 2. 把 redux 的 dispatch 注入 Pastate 模塊中

完成!這時你就能夠在 redux 應用中漸進式地使用 pastate 啦!
若是你在使用 dva.js 等基於 redux 開發的框架,一樣能夠用這種方式嵌入 pastate 模塊。

開發調試工具

因爲 pastate 內部使用 redux 做爲多模塊引擎,因此你能夠直接使用 redux devtools 做爲 pastate 應用的調試工具。Pastate 對其作了友好支持,你無需任何配置,就能夠直接打開 redux devtools 來調試你的應用:

redux devtools

使用 redux devtools 不要求 你把 pastate 嵌入到原生 redux 應用中,你不須要懂得什麼是 redux,在純 pastate 項目中就可使用 redux devtools!

中間件

內置中間件

Pastate 目前實現了基於 actions 的中間件系統,可用於對 actions 的調用進行前置或後置處理。Pastate 內置了幾個實用的中間件生成器

  • logActions(time: boolean = true, spend: boolean = true, args: boolean = true): 把 actions 的調用狀況 log 到控制檯
  • syncActions(onlyMutations: boolean = false): 把每一個 action 都轉化爲同步 action, 方便互相調用時的調試觀察每一個 action 對數據的改變狀況
  • dispalyActionNamesInReduxTool(onlyMutations: boolean = false): 把 actions 名稱顯示在 redux devtools 中,方便調試

自定義中間件

你也能夠很輕鬆的定義中間件,pastate 中間件定義方式和 koa 中間件相似,例如咱們定義一個簡單的 log 中間件:

const myLogMiddleware = function (ctx, next) {
    let before = Date.now();
    next();
    console.log(ctx.name + ': '+ (Date.now() - before) + 'ms');
}
  • ctx 參數是上下文(context)對象,包括以下屬性:
type MiddlewareContext = {
    name: string, // action 的名稱
    agrs?: IArguments, // action 的調用參數
    return: any, // action 的返回值
    store: XStore // action 綁定的 store
}
  • next 參數是下一個中間件或已作參數綁定的 action 實體, 你能夠實現本身的中間件邏輯,決定要不要調用或在何時調用 next。

編譯與部署

Pastate 推薦使用 create-react-app 來做爲應用的初始化和開發工具,create-react-app 不僅是一個簡單的 react 應用模板,它還爲咱們提供了很是完善的 react 開發支持,詳見其文檔。

在 pastate 應用中,你能夠簡單的使用默認的 build 指令來編譯應用:

$ npm run build
或
$ yarn build

其餘編譯和部署方式請參考這裏

Pastate 在編譯以後僅爲 ~28kb, gzip 以後僅爲 ~9kb,很是輕便。Pastate 包的總體結構以下(圖中顯示的是未 gzip 的大小):
 pastate 包結構

下一章,咱們來詳細介紹 pastate 的原理。

相關文章
相關標籤/搜索