最近在学react,官方的英文文档看起来甚是有意思,但 talk is cheap, show me the code。所以先手撸一个 todo list,后面再升级引入 react-redux,便于状态管理。
todoList的功能如下:
(1)用户可输入新的内容,点击 "Add todo"添加,默认初始状态是未完成(incomplete);
(2)用户通过勾选待做事项前的方框,将该事项标记为完成状态(completed);
(3)用户通过底部三个按钮,可按事项的完成状态分类别查看。
这个应用麻雀虽小五脏俱全,效果图如下。
fig2
fig3
在开始写代码实现之前,一定要先分析好业务逻辑,再结合UI取拆分组件,尤其要考虑好 state、props 中的数据以及它们所在的组件层级,要遵守 react 的设计思想。
这里定义了五个组件,TodoApp、AddTodo、TodoList、Todo、VisibilityFilters,介绍如下:
(1)TodoApp:应用的入口组件,层级最高,AddTodo、TodoList、VisibilityFilters 都在这里进行渲染(render)。
(2)AddTodo:包含一个输入框(input)和一个“Add todo ”按钮,以便用户添加待做事项(todo)。
(3)TodoList :是 Todo 组件的父级组件,展示由 Todo 组件构成的事项列表,不过仅展示符合 VisibilityFilters 组件中确定的当前过滤条件的事项。
(4)Todo:渲染单个事项,每个事项内容前面有复选框供用户点击标记事项的完成状态。
(5)VisibilityFilters:渲染决定事项是否显示的过滤条件,用户可点击设置。
组件的定义、功能、层级关系以及用户交互致使状态改变的地方都已说明完毕,代码较多就不贴了,要看请点这里
,欢迎指正。(纯手撸,只使用了 react 本身的状态管理、数据流动机制,未引入 redux),尽管要实现的功能并不复杂,但是这里面的状态管理已经不简单了。
下面将引入redux,在借助 redux 进行状态管理后,组件本身的代码就简洁多了,因为状态相关逻辑代码被提取放置到专门的文件中,如下图所示的 redux 文件目录。
专门负责状态管理的 redux 文件
现在简要介绍下redux 部分的组织结构:
(1)Store: 可视为状态(state)的容器,本应用的 state 有: todos,visibilityFilters,这部分代码很少,主要处理在 reducers 中。
(2)Action Creators:状态(state)是通过发送(dispatch)动作(action)来间接改变的,Action Creators 这部分对应 action.js 文件,用来生成动作(action),本应用中的动作有 ADD_TODO、TOGGLE_TODO、SET_FILTER,以下是 ADD_TODO 的示例,addTodo 函数是 action creator,返回的对象就是一个 action(由类型,有效内容定义)。
export const addTodo = content => ({
type: ADD_TODO,
payload: {
id: ++nextTodoId,
content
}
});
(3)Reducers:这部分用来具体规定 动作(action)如何改变 状态 (state),注意对整体状态作划分处理,如下 visibilityFilter reducer 只负责 visibilityFilter 这部分状态。
const initialState = VISIBILITY_FILTERS.ALL;
const visibilityFilter = (state = initialState, action) => {
switch (action.type) {
case SET_FILTER: {
return action.payload.filter;
}
default: {
return state;
}
}
};
(4)Selectors:select from store combining information from multiple reducers,比较负责的状态数据选择逻辑放这里会使得代码更加清晰可维护。
通过 connect 函数让组件与 store 连接,该函数可传入两个可选参数 mapStateToProps 和 mapDispatchToProps ,这两个参数的全称很好地诠释了它们的作用,前者是从整体 state 状态中取出被连接的组件需要的部分(组件被动接收状态),后者赋予组件(及其内部子孙组件,即使子孙组件未通过 connect函数与全局 state 连接)改变 state 的能力(组件主动改变状态),前者要传入的部分状态(如以下示例中的 todos)与后者要传入的 dispatch 函数(以下示例中的 toggleTodo),在被连接组件(TodoList)中都是通过 props 来获取。
export default connect(
state=>({todos:getTodosByVisibilityFilter(state)}), // mapStateToProps
{toggleTodo} // mapDispatchToProps
)(TodoList)
被连接的组件(<TodoList>)在 react 组件结构中被嵌套在 <Connect(TodoList)>组件中,在chrome中通过 React 开发者工作查看如下:
react中的组件嵌套结构
reference:
1
[2] react 官网文档
[3] redux 官网文档
网友评论