redux的三个核心概念
- action
- 动作对象
- 包含两个属性
- type:表示属性,值为字符串,必要属性(初始化的时候传@@init@@)
- data:数据属性,值类型随意,可选属性
- 例子:
{type: 'ADD_STUDENT', data:{name:'tom',age:18}}
- 同步action就是前面说的三个条件,还有异步action,异步action就是一个函数了,不是对象了,但是通常来说,异步action里面会调用同步的action。需要下载额外的组件(redux-thunk),并且,使用的时候,还要从redux中去除一个中间件
(applyMiddleware)
- reducer
- 用于初始化状态,加工状态
- 加工时,根据旧的state和action,产生新的state的纯函数
- 多个reducer需要使用combineReducers合并
- store
- 将state、action、reducer联系在一起
- 如何得到此对象?
- src文件夹下面新建一个文件下redux
- redux文件夹里面新建自己需要的文件,store.js文件必须,其他你需要什么新建什么,我们这里需要给A组件服务的reducer,所以起名为AReducer
- 此对象的功能
- getState():得到state
- dispatch(action):分发action,触发reducer调用,产生新的state
- subscribe(listener):注册监听,当产生新的state时,自动调用,listener是一个函数
代码演示
// store.js
// 同步action
// 引入createStore,用于创建redux中最核心的store
import {createStore} from 'redux'
// 引入为A组件服务的reducer
import AReducer from './reducers'
// 下面这两行可以合在一起 => export default createStore(AReducer)
const store = createStore(AReducer)
export default store
// 异步action
// import {createStore,applyMiddleware} from 'redux'
// import thunk from 'redux-thunk'
// import AReducer from './reducers'
// export default createStore(AReducer,applyMiddleware(thunk))
// AReducer.js
// 1.该文件是用于创建一个为A组件服务的reducer,其本质是一个函数
// 2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
// 假定这个A组件是一个用于求和的组件
import {JIA, JIAN} from './constant'
const initState = 0 // 初始化的时候可以用的上
export default function aReducer (preState=initState,action) {
// 从action对象中获取:type,data
const {type,data} = action
// 根据type决定如何加工数据
switch (type) {
case JIA:
return preState + data
case JIAN:
return preState - data
default:
return preState
}
}
// A.js
import React, { Component } from 'react'
import { Select, Button } from 'antd'
import store from '../../../redux/store'
import {jiaAction,jianAction,jiaAsyncAction} from '../../../redux/AAction'
const { Option } = Select
export default class Count extends Component {
state = {
options: [1,2,3],
val: 1
}
componentDidMount() {
store.subscribe(() => {
this.setState({})
})
}
jia = () => {
const {val} = this.state
store.dispatch(jiaAction(val))
}
jian = () => {
const {val} = this.state
store.dispatch(jianAction(val))
}
jiaAsync = () => {
const {val} = this.state
store.dispatch(jiaAsyncAction(val,500))
}
selectChange = (val) => {
this.setState({val})
}
render() {
const {options,val} = this.state
return (
<div>
<div>最后的和为:{store.getState()}</div>
<Select ref={c => {console.log(c);this.selectNumber = c}} value={val} onChange={this.selectChange}>
{
options.map((item) => {
return <Option value={item} key={item}>{item}</Option>
})
}
</Select>
<Button onClick={this.jia}>+</Button>
<Button onClick={this.jian}>-</Button>
<Button onClick={this.jiaAsync}>异步+</Button>
</div>
)
}
}
上面三个文件就可以凑成一个精简版本的reduce,加上下面两个文件,就可以是完整版的reduce了。
// AAction.js
// 把action对象提取出来,专门一个文件用于生成action
import {JIA, JIAN} from './constant'
// 同步action
export const jiaAction = data => ({type:JIA, data})
export const jianAction = data => ({type:JIAN, data})
// 异步action
export const jiaAsyncAction = (data,time) => {
retrun (dispatch) => {
// 业务代码部分了
setTimeout(() => {
dispacth(jiaAction(data))
},time)
}
}
// constant.js
// 常量文件,用于定义一些常量,便于直接应用,也可以防止程序员手动写错了
export const JIA = 'jia'
export const JIAN = 'jian'
react-redux
这是react官方出的redux的,因为大家喜欢用redux,所以官网出了一个这个,但是有自己的用法,主要是想把组件区分开,一类是专注于UI的UI组件,还有一个事专注与redux打交道的容器组件,容器组件包裹UI组件。
// App.js
import './App.css';
import Count from "./container/count"; // 这个是容器组件
import store from './redux/store'
function App() {
return (
<div className="App">
<Count store={store}/>
</div>
);
}
export default App;
// count.js (这是容器)
import {connect} from "react-redux";
import CountUI from "./components/count"; // UI组件
import {jiaAction} from '../../../redux/AAction'
// 这个函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value。(用于传递状态)
function mapStateProps(state) {
retrun {
count: state
}
}
// 这个函数返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value。(用于传递操作状态的方法)
function mapDispatchProps(dispatch) {
retrun {
jia: (number) => {
dispatch(jiaAction(number))
}
}
}
export default connect(mapStateProps,mapDispatchProps)(CountUI);
react-redux极简写法
// count.js容器组件和UI组件放在一起
import React, { Component } from 'react'
import {connect} from "react-redux";
import {jiaAction} from '../../../redux/AAction'
class Count extends Component {
state = {
options: [1,2,3],
val: 1
}
jia = () => {
const {val} = this.state
this.props.jia(val)
}
selectChange = (val) => {
this.setState({val})
}
render() {
const {options,val} = this.state
return (
<div>
<div>最后的和为:{store.getState()}</div>
<Select ref={c => {console.log(c);this.selectNumber = c}} value={val} onChange={this.selectChange}>
{
options.map((item) => {
return <Option value={item} key={item}>{item}</Option>
})
}
</Select>
<Button onClick={this.jia}>+</Button>
</div>
)
}
}
export default connect(
state => ({count: state}),
{
jia:jiaAction
}
)(CountUI);
// App.js
import './App.css';
import Count from "./container/count"; // 这个是容器组件
function App() {
return (
<div className="App">
<Count />
</div>
);
}
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import store from './redux/store'
import {Provider} from "react-redux";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);