React 教程第十五篇 —— 項目應用

實現

該案例是以中間件調用 nodejs 的公共接口,實現一個數據列表。javascript

源碼下載:https://github.com/dk-lan/rea... html

效果預覽java

用戶名和密碼都爲空node

源碼下載後執行下面步驟例可查看效果react

  • npm install
  • npm start

Redux 中間件的問題之做用域

在 Redux 中使用中間件能夠解決不少問題,但也會有個致命的問題,那就是在同一個組件中屢次調用同一個組件,那就會形成做用域污染。git

本案例中是這樣的場景:github

  • 如今要實如今組件cnode中動態加載數據,在該組件中還會有一個輸入框,點擊時彈窗動態加載一個數據列表,雙擊數據列表進行填充到對應的輸入框中
  • 有一個組件datagrid,用於動態加載數據,ajax 加載使用了中間件。
  • 有一個組件modal,該組件用到彈窗加載一個數據列表datagrid
  • 在組件cnode中調用了組件datagrid<Datagrid config={this.props.cnode.config}/>
  • 在組件cnode中同時調用了組件modal,而組件modal又調用了組件datagrid
  • 這個時候兩個datagrid的數據源就會衝突,後面加載的數據衝突了前面加載的。
  • 解決方案是在數據源中對數據源做用域隔離

對象做用域隔離

每次調用組件datagrid時給一個別名name,別名不能重複,用於做用域隔離

static defaultProps = {
    cnode: {
        config: {
            url: 'https://cnodejs.org/api/v1/topics',
            data: {page: 1, limit: 10},
            cols: ['title', 'reply_count', 'top', 'create_at', 'last_reply_at'],
            name: 'cnode'
        }           
    },
    modal: {
        config: {
            type: 'datagrid',
            url: 'https://cnodejs.org/api/v1/topics',
            data: {page: 3, limit: 5},
            cols: ['title'],
            name: 'modal'
        } 
    }
}

Action 中將別名name派發到中間件

export function refresh(_config){
    return {
        types: [constants.Requesting, constants.Requested, constants.RequestError],
        url: _config.url,
        method: _config.method || 'get',
        data: _config.data || {},
        name: _config.name
    }
}

在中間件將別名name一派發到Reducer

let _action = {
    type: constants.Requested,
    name,
    result: res.data
}
dispatch(_action)

Reducer中兼容有別名和沒別名的狀況,若是有別名,就將數據源做用域隔離

if(action.name){
    _state[action.name] = _state[action.name] || {};
    _state[action.name].dataset = action.result;
} else {
    _state.dataset = action.result;
}

DatagridComponent中判斷是否有別名,兼容有別名和沒別名的狀況,分別操做不一樣的數據源

let ds = this.props.dataset;
let name = this.props.config.name;
if(name){
    ds = ds[name] ? ds[name].dataset : []
} else {
    ds = ds.dataset || [];
}
相關文章
相關標籤/搜索