Redux 入门
状态管理,第一次听到这个词要追溯到去年年底。那时,Flux 红透半边天,而 Reflux 也是风华正茂。然而,前一阵一直在忙其他的事,一直没时间学学这两个库,到现在 Redux 似乎又有一统天下的趋势。 那就来看看,Redux 是凭借什么做到异军突起的。 What's ReduxRedux 是一个 JavaScript 应用状态管理的库,它帮助你编写行为一致,并易于测试的代码,而且它非常迷你,只有 2KB。 Redux 有一点和别的前端库或框架不同,它不单单是一套类库,它更是一套方法论,告诉你如何去构建一个状态可预测的应用。 Why using Redux随着单页应用变得越来越复杂,前端代码需要管理各种各样的状态,它可以是服务器的响应,也可能是前端界面的状态。当这个状态变得任意可变,那么你就可能在某个时间点失去对整个应用状态的控制。 Redux 就是为了解决这个问题而诞生的。 简短地说,Redux 为整个应用创建并管理一棵状态树,并通过限制更新发生的时间和方式,而使得整个应用状态的变化变得可以被预测。 除此之外,Redux 有着一整套丰富的生态圈,包括教程、中间件、开发者工具及文档,这些都可以在官方文档中找到。 How to use Redux三大原则在使用 Redux 之前,你必须要谨记它的三大原则:单一数据源、
Action就如之前提到的, 下面就是一个 const ADD_TODO = 'ADD_TODO' // action { type: ADD_TODO,text: 'Build my first Redux app' } 可以看到 用一个字符串类型的 除了 在现实场景中, 上面的那个例子就会变为: function addTodo(text) { return { type: ADD_TODO,text } }
Reducer
在 Redux 应用中,所有的 在设计过程中,你会发现你有时需要在 { todos: [ { text: 'Consider using Redux',completed: true,},{ text: 'Keep all state in a single tree',completed: false } ] } 注意:在处理复杂应用时,建议尽可能地把 现在我们已经确定了 (previousState,action) => newState 还记不记得三大原则? 没错,最后一点使用纯函数进行修改,所以,永远不要在
将这些铭记于心后,就能创建对应之前 const initialState = { todos: [] } function todoApp(state = initialState,action) { switch (action.type) { case ADD_TODO: return { ...state,todos: [ ...state.todos,{ text: action.text,completed: false } ] } default: return state } } 注意:
这样一个 case TOGGLE_TODO: return { ...state,todos: state.todos.map((todo,index) => { if (index === action.index) { return { ...todo,completed: !todo.completed } // 时刻谨记不要修改 state,保证 reducer 是纯函数 } return todo }) } 从例子中可以发现,当对 此时,我们就可以将这些相互独立的 // todos reducer function todos(state = [],action) { switch (action.type) { case ADD_TODO: return [ ...state,{ text: action.text,completed: false } ] case TOGGLE_TODO: return state.map((todo,index) => { if (index === action.index) { return { ...todo,completed: !todo.completed } // 时刻谨记不要修改 state,保证 reducer 是纯函数 } return todo }) default: return state } } // main reducer function todoApp(state = initialState,action) { switch (action.type) { case ADD_TODO: case TOGGLE_TODO: return { ...state,todos: todos(state.todos,action) } default: return state } } 这就是所谓的 注意:每个 由于,每个 // main reducer function todoApp(state = initialState,action) { return { todos: todos(state.todos,action) } } 最后,Redux 提供了
最终,我们的 main // main reducer const todoApp = combineReducers({ todos // 等价于 todos: todos(state.todos,action) }) 随着应用的膨胀,你可以将拆分后的 import { combineReducers } from 'redux' import * as reducers from './reducers' const todoApp = combineReducers(reducers) export default todoApp
Store
根据已有的 import { createStore } from 'redux' import todoApp from './reducers' let store = createStore(todoApp) 这样,整个应用的 import { addTodo,toggleTodo } from './actions' // 打印初始状态 console.log(store.getState()) // 注册监听器,在每次 state 更新时,打印日志 const unsubscribe = store.subscribe(() => console.log(store.getState()) ) // 发起 actions store.dispatch(addTodo('Learn about actions')) store.dispatch(addTodo('Learn about reducers')) store.dispatch(addTodo('Learn about store')) store.dispatch(actions.toggleTodo(0)) store.dispatch(actions.toggleTodo(1)) // 停止监听 unsubscribe(); 运行代码,控制台中就能看到下面的输出。
Data flow时刻谨记一点:严格的单向数据流是 Redux 架构的设计核心。 也就是说,对 Take a try with Angular之前的举例已经将 redux 最基本的一套生命周期处理展示完毕了,但没有个界面显示总是不那么令人信服。Redux 官网的例子是将 Redux 同 React 一起使用,但如同一开始说的,Redux 更是一套方法论,它不单可以和 React 一同使用,也可以和 Angular 等其他框架一同使用。 虽然,同官网用的是不同的框架,但概念是相通的。 首先,页面都是由组件构成,组件又分为两大类:容器组件(Smart/Container Components)和展示组件(Dumb/Presentational Components)。
简单来说,容器组件就是通过 可以说,容器组件是整个界面显示的核心。 // todos/index.js import angular from 'angular' import template from './todos.html' import controller from './todos' const todoContainer = { controller,template } export default angular.module('todoContainer',[]) .component('todoContainer',todoContainer) .name // todos/todos.js import store from '../../store' import actions from '../../actions' export default class TodosContainController { $onInit() { // 注册监听器,在每次 state 更新时,更新页面绑定内容 this.unsubscribe = store.subscribe(() => { console.log(store.getState()) this.todos = store.getState().todos }) } addTodoItem(text) { store.dispatch(actions.addTodo(text)) } toggleTodoItem(index) { store.dispatch(actions.toggleTodo(index)) } $onDistory() { // 销毁监听器 this.unsubscribe() } } // todos/todos.html <div> <add-todo add-todo-fn="$ctrl.addTodoItem(text)"></add-todo> <todo-list todo-list="$ctrl.todos" toggle-todo-fn="$ctrl.toggleTodoItem(index)"></todo-list> </div> Redux 官网并不建议直接这样使用 鉴于展示组件与 redux 并没有太大的相关,就不在这里赘述了,有兴趣可以去 github 上查看。 至此,一个简单的基于 Angular 并运用 Redux 的 todo MVC 应用就完成了。 最后如果你熟悉 Flux,那么这篇图文并茂的文章获取会对你有很大的帮助。 如果你是和我一样直接接触 Redux,那官方文档是你的首选。 当然,你一定得看看 Redux 作者 Dan Abramov 自己录制的视频,它会对你理解 Redux 有极大的帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |