什么是Redux?
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
简单来说,redux就是一个存储数据的仓库。
相当于Vue中的Vuex,在多个组件之间共享数据。
安装Redux
npm install --save redux
附加包
多数情况下,你还需要使用 React 绑定库和开发者工具(根据需要安装)。
npm install --save react-redux
npm install --save-dev redux-devtools
Redux应用场景
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
三大原则
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
为了描述 action 如何改变 state tree ,你需要编写 reducers。
基本概念
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
import { createStore } from 'redux';
const store = createStore(fn);
createStore可以接受一个函数作为参数,返回新生成的store对象。
Store对象包含所有数据。如果想得到某个时间点的数据,就要对 Store 生成快照。这种时间点的数据集合,就叫做 State。State存在于Store中。可以通过 store.getState()得到
import { createStore } from 'redux';
const store = createStore(fn);
const state = store.getState();
Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。
-
Action
action用来传递操作 State 的信息
State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。State的唯一办法就是使用Action,他会负责把数据送到store中的。
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'
};
这里Action的类型是:“ADD_TODO”,携带的信息是:‘Learn Redux’。
Action是一个对象,type属性是必须的,表示Action的名称或者类型,其他属性可以自由设置,来携带自己需要的信息。一般来说State就是由Action的type值进行判断,然后改变的
使用redux
需要手动在src目录下新建store文件夹,在store文件夹中创建index.js文件
src目录下的Store文件就是用来管理共享数据的脚本文件夹
index.js:用来统一暴露store和操作Store的入口,引入redux模块并使用模块中的createStore方法来创建store并暴露出来。
import { createStore } from 'redux';
import reducer from './reducer'
let store=createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store
加入window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
是为了能在谷歌浏览器中用redux devtools调试工具。
reducer.js:这是存数据和改变数据方法的地方。
export default (state,action)=>{
return state
}
在reducer.js中需要注意的地方
- 不能直接在这里改变数据,而是要return给store让store来汇总改变数据。
- 改变数据的方法中不能有任何异步的方法
- 每个action改变数据都会传入一个type常量来判断要改变的对象和对应进行的操作。
redux-devtools调试工具
在谷歌浏览器打开【更多工具】->【扩展程序】->打开chrome网上商店搜索Redux DevTools并安装
- 需要在页面中引入对应的redux文件
- store.getState()可以取到所有的store的数据
- store.subscribe(callback)在store数据发生改变的时候会触发这个方法,可以传入一个回调函数来进行数据改变后相应的操作
- store.dispatch(Object)通过这个方法可以改变store的数据,你可以传入一个对象这个对象中要有type和value这两个值,type是前面说到的常量(reducer通过常量来判断要进行什么操作),action是改变后的值
import React,{Component} from 'react';
import store from './store'
import { Input, Button, List } from 'antd';
import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'
import './operation.css'
class Operation extends Component{
constructor(props){
super(props)
this.state= store.getState()
this.handleChange=this.handleChange.bind(this)
this.handleLister=this.handleLister.bind(this)
// 为store 添加监听器,当 reducer 中的函数返回新的值,store中的值发生变化后就执行
store.subscribe(this.handleLister)
}
render(){
return (
<>
<div className="header">
<Input
placeholder="待办事项"
className="input"
value={this.state.inputValue}
onChange={this.handleChange} />
<Button type="primary" onClick={this.handleAdd}>添加</Button>
</div>
<div className="body">
<List
size="small"
header={<div>待办事项</div>}
footer={<div>Footer</div>}
bordered
dataSource={this.state.todoList}
renderItem={item => <List.Item style={{lineHeight:'30px'}}>{item}</List.Item>}
/>
</div>
</>
)
}
handleChange(e){
const action={
type:'change_input',
value:e.target.value
}
store.dispatch(action)
}
// 监听函数
handleLister(){
this.setState(
store.getState()
)
}
handleAdd(){
const action={
type:'add'
}
store.dispatch(action)
}
}
export default Operation