Redux是react的一个比较经典的状态管理工具,相当于vue中的vuex,无论是移动端还是 pc 端,当我们使用 React 或者 vue 开发组件化的单页面程序时,组件之间的通讯,也就是信息共享是一个非常大的问题。
比如,用户登录之后存储的用户信息,登录名、状态、头像以及用户的操作,如收藏、点赞、评论等等,会在程序的多个组件中用到。那么,这些组件在用到用户信息时,每次使用都重新获取一遍就很不科学了。因此每个产品都需要一个管理多组件使用的公共信息的功能,这就是 Redux 的作用。
1.redux和react-redux的区别
react-redux则是一个更快捷方便的状态管理插件了,当然,必须结合redux使用,毕竟需要redux来创建store,react-redux它会将redux中的派发动作和数据的更新等数据和逻辑处理都自动生成,你只需要负责做页面层的渲染,下面依次介绍。
2.redux的三大原则
单一数据源,仓库是唯一的,就是一个程序中,只能有一个store,存储着全局的数据。
state是只读的,使用纯函数来执行修改(这里需要使用到浅拷贝和深拷贝,保证之前的数据是可追溯的,而不是直接对state进行修改。)
什么时候使用:某个组件的状态需要共享,某个状态需要在任何地方都可以拿到,一个组件需要改变全局状态,一个组件需要改变另一个组件的状态。
3.基本代码
store中的几个重要方法:
dispatch(action) 分发
subscribe(listener) 订阅
getState()获取数据(状态)
npm i redux - -save //安装
import {createStore} from "redux"
//设置状态的初始值
var initstate={
n:5
}
var reducer=(state=initstate,action)=>{ //数据和动作
//在这里定义计算规则,并返回新的state
switch (action.type) {
let newstate={...state};//浅拷贝,保证源数据可追溯
case 'INCREMENT':
return newstate.n + 1
case 'DECREMENT':
return newstate.n - 1
default:
return newstate
}
}
//根据计算规则生成 store
var store =createStore(reducer) 仓库是唯一的
// 定义数据(即 state)变化之后的派发规则
store.subscribe(() => {
console.log('current state', store.getState())
})
// 触发数据变化
store.dispatch({type: 'INCREMENT'})
store.dispatch({type: 'INCREMENT'})
store.dispatch({type: 'DECREMENT'})
export default store;
详细解释:
首先是创建store用来管理数据,具体的管理形式:用户在view上进行一系列操作,而每一个操作都对应一个action,要通过一个函数来触发数据的变化,即dispatch。Store对象通过调用dispatch方法,传入上次的状态(previousState)和操作(action),经过Reducer针对不同的action,改变previousState的值,然后返回一个newState,然后Store对象可以通过getState()方法,获取这个新状态。最后进行相应的视图更新。
4.单向数据流:
严格的单向数据流是 Redux 架构的设计核心:
用户行为引起调用store.dispatch(action)
调用reduser函数:两个参数,当前的state和action
返回计算过的state
触发所有订阅store.subscribe(listener)
5.react-redux
需要自己去额外安装的。在React-redux中有两个比较关键的概念:Provider和connect方法。
一般我们都将顶层组件包裹在Provider组件之中,这样的话,所有组件就都可以在react-redux的控制之下了,但是store必须作为参数放到Provider组件中去
这样所有组件都能够访问到Redux中的数据。
connect方法接受两个参数:mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。
import React, { Component } from 'react'
import {connect} from 'react-redux';
import actionCreator from './actionCreator';
class List extends Component {
render() {
let {list,length,changeFinish,removeAction:remove} = this.props;
return (
{
list.map((item)=>{
return -
{item.text}
})
}
{length}
)
}
}
var mapState = (state)=>{
let arr =state.todos.todos.filter((item)=>item.flag)
return {
list:state.todos.todos,
//相当于计算属性,取出 flag是true值的个数
length:arr.length
}
}
export default connect(mapState,actionCreator)(List);
actionCreator也不需要多说了,就是对dispatch派发的方法做一个集中管理。
一个store可以添加多个reducer,可以分文件创建其它的操作,便于分类管理。只要创建store的时候使用combineReducers全部绑定到一起就可以了。
import { combineReducers } from "redux";
import todoReducer from '../components/todos/reducer'
var reducer=combineReducers({
todos:todoReducer,
one:oneReducer
})
export default reducer;
const initialState = {
todos:[
{
"id":1,
"text":'aaaa',
"flag":false,
visible:true
}
]
}
export default (state = initialState, action) => {
switch (action.type) {
case 'ADD':
var newState ={ ...state};
newState.todos.push({
id:Date.now(),
text:action.text,
flag:false,
visible:true
})
return newState;
case 'FINISH':
var newState ={ ...state};
newState.todos.forEach((item)=>{
if(item.id===action.id){
item.flag=!item.flag
}
})
return newState;
case 'REMOVE':
var newState =JSON.parse(JSON.stringify(state)); //此处为深拷贝
var index = newState.todos.findIndex((item)=>item.id===action.id);
newState.todos.splice(index,1);
return newState;
case 'FIND':
var newState=JSON.parse(JSON.stringify(state));
newState.todos.forEach((item)=>{
if(item.text.includes(action.text)){
item.visible=true;
}
else{
item.visible=false;
}
})
console.log(newState.todos);
return newState;
default:
return state
}
}