阿里前端推出新的 React 框架:Mirror

感謝阿里前端工程師@李凌豪投稿,文章首發在 qianduan.guru。

Mirror 是一款基於 React、Redux 和 react-router 的前端框架,簡潔高效、靈活可靠。

為什麼?

我們熱愛 React 和 Redux。但是,Redux 中有太多的樣板文件,需要很多的重複勞動,這一點令人沮喪;更別提在實際的 React 應用中,還要集成 react-router 的路由了。

一個典型的 React/Redux 應用看起來像下面這樣:

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),那麼代碼就更繁瑣了。

使用 Mirror 重寫

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)。

而且,這行代碼:

actions.todos.add("a new todo")

完全等同於這行代碼:

dispatch({ type: "todos/add", text: "a new todo"})

完全不用關心具體的 action type,不用寫大量的重複代碼。簡潔,高效

非同步 action

上述代碼示例僅僅針對同步 action。

事實上,Mirror 對非同步 action 的處理,也同樣簡單:

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

查看 文檔 了解更多。

誰在使用?

Mirror 由阿里巴巴 FGT 前端團隊開發,目前在整個集團內部已有多個使用 React 技術棧的團隊使用。


推薦閱讀:

基於 Webpack 的應用包體尺寸優化
React 實現一個漂亮的 Table
React Conf 2017 不能錯過的大起底——Day 1!
解析 Redux 源碼
我對Flexbox布局模式的理解

TAG:React | Redux | 前端框架 |