感谢阿里前端工程师@李凌豪投稿,文章首发在 qianduan.guruhtml
Mirror 是一款基于 React、Redux 和 react-router 的前端框架,简洁高效、灵活可靠。前端
咱们热爱 React 和 Redux。可是,Redux 中有太多的样板文件,须要不少的重复劳动,这一点使人沮丧;更别提在实际的 React 应用中,还要集成 react-router
的路由了。react
一个典型的 React/Redux 应用看起来像下面这样:git
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 = 0
export 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
),那么代码就更繁琐了。github
Todos.js
import mirror, { actions } from 'mirrorx'
let nextId = 0
mirror.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
)。npm
并且,这行代码:redux
actions.todos.add('a new todo')复制代码
彻底等同于这行代码:api
dispatch({
type: 'todos/add',
text: 'a new todo'
})复制代码
彻底不用关心具体的 action type
,不用写大量的重复代码。简洁,高效。bash
上述代码示例仅仅针对同步 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 技术栈的团队使用。