在介绍redux之前,大家应该了解redux的作用,为什么会有redux的出现?
我们知道react是现在特别火的一个前端框架,很多知名企业都在使用react,所以我们应该要知道react的定位。react的其实是一个ui框架,很多事情react并不是自己来完成,而是交给其他组件来完成。比如react基于state的数据管理交给redux来做,ajax请求的发送交给axios来做等等。react父子组件之间的数据传递其实是很简单的,如果子组件想修改父组件中的state,我们就得先在父组件中定义函数,该函数的作用就是setState修改父组件的state中的数据,那子组件就可以利用props接受父组件传递过来的函数,来间接的调用父组件中修改satate的方法,来达到目的。但是当一个页面非常的复杂,所有的组件不是简单的父子关系,甚至会出现十几层的组件调用,那这种场景下,如果我们还是用原来的方式一层一层的进行数据传递,就会出现‘曼妥思与可乐效应’。 所以这篇文章其实是告诉大家redux是如何来帮助react进行数据管理的,但是有句话要说前面,不是学会了redux之后,所有的项目都用redux来进行数据管理,我们不仅需要知道redux的有点,还需要知道redux的缺点,知道哪些场景是不适合使用redux的。
redux的三大核心
action
action这个概念其实不难理解,我们在需要修改state的数据的时候,会首先发出一个action,一般的action长这样:
{
type: 'ADD_TODO',
text: 'Build my first Redux app'
}
每一个action都有type都有一个type,标记着这个任务的类型,它的作用就是在后面进行修改state数据的时候告诉reduer:什么样action我应该进行对应的操作。大家其实也看得出来,这个type是有手工定义的一个字符串,那既然是常量字符串我们就应该将他管理起来,创建函数返回单一的action,创建常量来管理type,从而进行父组件的代码优化。
function addTodo(text) {
return {
type: 'ADD_TODO',
text
}
}
//contants.js
export const VisibilityFilters = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
text就是传递的数据参数,reducer在进行修改state值得时候可能会利用到这里的参数,所以这里的text就起到这样一个作用。其实我们可以把action理解为信鸽,每一个action都是消息的传递者,传递的数据流就是绑在信鸽腿上的信。
store:
我们说action是消息的传递者,那么action到底传递给谁呢?那我又是如何监听state被reducer修改了呢?
store其实是redux进行数据管理的核心。它提供createStore 的getState()方法来获取state,通过dispatch(action)来派发action,通过suscribe来监听state数据是否发生改变,需要抢到一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合而不是创建多个 store。
首先我们来看一下store如何创建:
1、首先我们在src目录下创建一个store文件夹,接着再建一个index.js文件
下面是store下面的index.js的内容:
import {createStore} from 'redux';
import reducer from './reducer';
const store = createStore(reducer);
export default store;
最后回到父组件再去使用这个store,下面的代码是个例子:
//todolist.js
import React, { Component } from 'react'
import 'antd/dist/antd.css';
import store from './store/index.js';
import {getInitList, getInputChangeAction, getAddTodoItem, getDeleteTodoItem} from './store/actionCreators';
import ToListUI from './TodoListUI';
class TodoList extends Component{
constructor(props){
super(props);
this.state = store.getState()
this.handleInputChange = this.handleInputChange.bind(this);
this.handleStoreChanged = this.handleStoreChanged.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
//监听store是否发生改变,一旦发生改变store就会执行subscribe函数
store.subscribe(this.handleStoreChanged);
}
render() {
return <ToListUI
inputValue={this.state.inputValue}
list={this.state.list}
handleInputChange={this.handleInputChange}
handleBtnClick={this.handleBtnClick}
handleItemDelete={this.handleItemDelete}
/>
}
componentDidMount(){
const action = getInitList();
store.dispatch(action);
// axios.get('/list.json')
// .then((res) => {
// const data = res.data;
// const action = initListAction(data);
// store.dispatch(action);
// })
//redux-thunk
// const action = getTodoList();
// //store如果发现这个action是个函数那么就会自动执行这个action函数
// //这就是actionCreators中getTodoList()方法会执行的原因
// store.dispatch(action);
}
handleStoreChanged() {
this.setState(store.getState());
}
handleInputChange(e){
const action = getInputChangeAction(e.target.value)
store.dispatch(action);
}
handleBtnClick(){
const action = getAddTodoItem();
store.dispatch(action);
}
handleItemDelete(index){
const action = getDeleteTodoItem(index);
store.dispatch(action);
}
}
export default TodoList;
我们首先将store给import进来,然后getState()获取到store下面的state赋值给当前组件下的state,每一个动作都派发一个action给reducer,下面reducre登场。
reducer:
reducer其实可以理解为store的秘书,store会把action告诉reducer,reducer也可以接收到store中state更新之前的state,最后根据action中定义的type做不同的事情,将修改后的state以一个新的state返回。
import {CHANGE_INPUT_VALUE,ADD_TODO_ITEM,DELETE_TODO_ITEM,INIT_LIST_ACTION} from './actionTypes';
const defaultState = {
inputValue: '闻声识雨',
list: []
}
//reducer可以接受state但是绝不能修改state,所以需要拷贝到newState
//纯函数指的是,给固定的输入,就一定会有固定的输出,而且不会有副作用
export default (state = defaultState, action) => {
if(action.type === CHANGE_INPUT_VALUE){
const newState = JSON.parse(JSON.stringify(state));
newState.inputValue = action.value;
return newState;
}
if(action.type === ADD_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state));
newState.list.push(newState.inputValue);
newState.inputValue = '';
return newState;
}
if(action.type === DELETE_TODO_ITEM){
const newState = JSON.parse(JSON.stringify(state));
newState.list.splice(action.index,1);
return newState;
}
if(action.type === INIT_LIST_ACTION){
const newState = JSON.parse(JSON.stringify(state));
newState.list = action.data;
return newState;
}
return state;
}
以上呢就是redux的三大核心的简单的介绍,但是需要搞懂,真是需要自己亲自实践一番,了解redux中这三个概念的数据流转,相互关系。
官网直通车:redux官网