Mirror 是一款基於 React、Redux 和 react-router 的前端框架,簡潔高效、靈活可靠。html
咱們熱愛 React 和 Redux。可是,Redux 中有太多的樣板文件,須要不少的重複勞動,這一點使人沮喪;更別提在實際的 React 應用中,還要集成 react-router
的路由了。前端
一個典型的 React/Redux 應用看起來像下面這樣:react
actions.js
export const ADD_TODO = 'todos/add'export const COMPLETE_TODO = 'todos/complete'export function addTodo(text) { return { type: ADD_TODO, text } }export function completeTodo(id) { return { type: COMPLETE_TODO, id } }複製代碼
reducers.js
import { ADD_TODO, COMPLETE_TODO } from './actions'let nextId = 0export default function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [...state, {text: action.text, id: nextId++}] case COMPLETE_TODO: return state.map(todo => { if (todo.id === action.id) todo.completed = true return todo }) default: return state } }複製代碼
Todos.js
import { addTodo, completeTodo } from './actions'// ...// 在某個事件處理函數中dispatch(addTodo('a new todo'))// 在另外一個事件處理函數中dispatch(completeTodo(42))複製代碼
看起來是否是有點繁冗?這仍是沒考慮 異步 action
的狀況呢。若是要處理異步 action
,還須要引入 middleware(好比 redux-thunk
或者 redux-saga
),那麼代碼就更繁瑣了。git
Todos.js
import mirror, { actions } from 'mirrorx'let nextId = 0mirror.model({ name: 'todos', initialState: [], reducers: { add(state, text) { return [...state, {text, id: nextId++}] }, complete(state, id) { return state.map(todo => { if (todo.id === id) todo.completed = true return todo }) } } })// ...// 在某個事件處理函數中actions.todos.add('a new todo')// 在另外一個事件處理函數中actions.todos.complete(42)複製代碼
是否是就簡單不少了?只需一個方法,便可定義全部的 action
和 reducer
(以及 異步 action
)。github
並且,這行代碼:npm
actions.todos.add('a new todo')複製代碼
徹底等同於這行代碼:redux
dispatch({ type: 'todos/add', text: 'a new todo'})複製代碼
徹底不用關心具體的 action type
,不用寫大量的重複代碼。簡潔,高效。api
上述代碼示例僅僅針對同步 action
。前端框架
事實上,Mirror 對異步 action
的處理,也一樣簡單:react-router
mirror.model({ // 省略前述代碼 effects: { async addAsync(data, getState) { const res = await Promise.resolve(data) // 調用 `actions` 上的方法 dispatch 一個同步 action actions.todos.add(res) } } })複製代碼
沒錯,這樣就定義了一個異步 action。上述代碼的效果等同於以下代碼:
actions.todos.addSync = (data, getState) => { return dispatch({ type: 'todos/addAsync', data }) }複製代碼
調用 actions.todos.addSync
方法,則會 dispatch 一個 type 爲 todos/addAsync
的 action。
你可能注意到了,處理這樣的 action,必需要藉助於 middleware。不過你徹底不用擔憂,使用 Mirror 無須引入額外的 middleware,你只管定義 action/reducer,而後簡單地調用一個函數就好了。
Mirror 徹底按照 react-router 4.x 的接口和方式定義路由,所以沒有任何新的學習成本。
更方便的是,Mirror 的 Router
組件,其 history 對象以及跟 Redux store
的聯結是自動處理過的,因此你徹底不用關心它們,只需關心你本身的各個路由便可。
並且,手動更新路由也很是簡單,調用 actions.routing
對象上的方法便可更新。
Mirror 的設計理念是,在儘量地避免發明新的概念,並保持現有開發模式的前提下,減小重複勞動,提升開發效率。
Mirror 總共只提供了 4 個新的 API,其他僅有的幾個也都是已存在於 React/Redux/react-router 的接口,只不過作了封裝和強化。
因此,Mirror 並無「顛覆」 React/Redux 開發流,只是簡化了接口調用,省去了樣板代碼:
在對路由的處理上,也是如此。
使用 create-react-app 建立一個新的 app:
$ npm i -g create-react-app $ create-react-app my-app複製代碼
建立以後,從 npm 安裝 Mirror:
$ cd my-app $ npm i --save mirrorx $ npm start