redux02

REACT-REDUX

REACT-REDUX 是把redux进一步封装,适配react项目,让redux操作更简洁

  • STORE文件夹中的内容和REDUX一模一样
  • 在组件调取使用的时候可以优化一些步骤

与传统的react相比

  1. 导出的不在是我们创建的组件,而是基于CONNECT构造后的高阶组件

    1
    export default connect([mapStateToProps], [mapDispatchToProps])([自己创建的组件])
  2. 以前我们基于SUBSCRIBE向事件池追加方法,如果容器状态信息发生改变,就会执行事件池里面的方法,达到组件重新渲染的目的;

  3. REACT-REDUX帮我们优化redux的使用:“所有用到REDUX容器状态信息的组件,都会向事件池中追加一个方法,当状态信息改变,通知方法执行,把最新的状态信息作为属性传递给组件,组件的属性值改变了,组件也会重新渲染”

Provider 根组件

作用就是把创建的STORE可以供内部任何后代组件使用(基于上下文完成的)

  • provider 组件中只允许出现一个子元素
  • 把项目的store基于属性传递给Provider(这样后代组件中都可以方便简洁的使用这个store)

connect 高阶组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default connect([mapStateToProps], [mapDispatchToProps])([自己创建的组件])
/*//=>把REDUX容器中的状态信息遍历,赋值给当前组件的属性(state)
let mapStateToProps = state => {
//=>state:就是REDUX容器中的状态信息
//=>我们返回的是啥,就把它挂载到当前组件的属性上(REDUX存储很多信息,我们想用啥就返回啥即可)
return {
...state.vote
};
};*/

/*
//=>把REDUX中的DISPATCH派发行为遍历,也赋值给组件的属性(ActionCreator)
let mapDispatchToProps = dispatch => {
//=>dispatch:STORE中存储的DISPATCH方法
//=>返回的是啥,就相当于把啥挂载到组件的属性上(一般我们挂载一些方法,这些方法中完成了DISPATCH派发任务操作)
return {
init(initData) {
dispatch(action.vote.init(initData));
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(VoteBase);
*/

VoteBase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import React from 'react';
import {connect} from 'react-redux';
import action from '../../store/action'

/*
* 相对于传统的REDUX,我们做的步骤优化
* 1. 导出的不在是我们创建的组件,而是基于CONNECT构造后的高阶组件
* export default connect([mapStateToProps], [mapDispatchToProps])([自己创建的组件]);
*
* 2. REACT-REDUX帮我们做了一件非常重要的事情:以前我们需要自己基于SUBSCRIBE向事件池追加方法,以达到容器状态信息改变,执行我们追加的方法,重新渲染组件的目的,但是现在不用了,REACT-REDUX帮我们做了这件事:“所有用到REDUX容器状态信息的组件,都会向事件池中追加一个方法,当状态信息改变,通知方法执行,把最新的状态信息作为属性传递给组件,组件的属性值改变了,组件也会重新渲染”
*/


class VoteBase extends React.Component {
/*constructor(props) {
super(props);
/!*
* 真实项目中我们会把REDUX容器中的状态信息获取到,赋值给组件的状态或者是属性(REACT-REDUX),这么做的目的是:当REDUX中的状态改变,我们可以修改组件内部的状态,从而达到重新渲染组件的目的
*!/

let reduxState = this.props.store.getState().vote;
this.state = {
...reduxState //=>包含title/n/m所有管理的属性
};
}

//=>在第一次加载执行,通过行为派发(VOTE_INIT)把REDUX中的信息赋值初始值
componentWillMount() {
this.props.store.dispatch(action.vote.init({
title: '我长的帅不帅!',
n: 0,
m: 100
}));
let reduxState = this.props.store.getState().vote;
this.setState({...reduxState});
}

//=>向发布订阅事件池中追加一个方法:监听REDUX容器中状态改变,状态改变重新渲染组件
componentDidMount() {
this.props.store.subscribe(() => {
let reduxState = this.props.store.getState().vote;
this.setState({...reduxState});
});
}*/

constructor(props) {
super(props);
console.log(this.props);
}

componentWillMount() {
this.props.init({
title: '我长的帅不帅?',
n: 0,
m: 100
});
}

render() {
let {title, n, m} = this.props;

return <div className='panel panel-default'>
<div className='panel-heading'>
<h3 className='panel-title'>
{title}
</h3>
</div>
<div className='panel-body'>
支持人数:<span>{n}</span>
<br/><br/>
反对人数:<span>{m}</span>
</div>
</div>;
}
}



export default connect(state => ({...state.vote}), action.vote)(VoteBase);//=>REACT-REDUX帮我们做了一件事情,把ACTION-CREATOR中编写的方法(返回ACTION对象的方法),自动构建成DISPATCH派发任务的方法,也就是mapDispatchToProps这种格式

VoteHandle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from 'react';
import {connect} from 'react-redux';
import action from '../../store/action';

class VoteHandle extends React.Component {
constructor(props) {
super(props);
}

render() {
let {support, against} = this.props;
return <div className='panel-footer'>
<button className='btn btn-success' onClick={support}>支持
</button>
&nbsp;&nbsp;&nbsp;&nbsp;
<button className='btn btn-danger' onClick={against}>反对
</button>
</div>;
}
}

export default connect(state => ({...state.vote}), action.vote)(VoteHandle);

action

ACTION中处理的事情暂时感觉很无聊:就是封装几个方法(都是需要DISPATCH派发任务修改状态时候执行的方法),方法返回的是当前派发任务时候传递的ACTION对象
REACT-REDUX中才会体验到这个封装的乐趣

action-types

1
2
3
4
5
6
//=>VOTE
export const VOTE_INIT = 'VOTE_INIT';//=>数据初始化
export const VOTE_SUPPORT = 'VOTE_SUPPORT';//=>支持
export const VOTE_AGAINST = 'VOTE_AGAINST';//=>反对

//=>PERSONAL

index.js

1
2
3
4
5
6
7
8
import vote from './vote';
// import personal from './personal';

let action = {
vote
// personal
};
export default action;

vote.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import * as TYPE from '../action-types';

let vote = {
support(){
return {
type: TYPE.TYPE.VOTE_SUPPORT
}
},
against() {
return {
type: TYPE.VOTE_AGAINST
};
},
init(initData = {}) {
return {
type: TYPE.VOTE_INIT,
...initData
};
}
}
export default vote;

reducer

index.js

合并REDUCER,为了保证每一个版块管理的状态信息不冲突,在REDUX中按照指定的名称单独划分版块的状态

1
2
3
4
5
6
7
8
9
10
{
vote:{
title:'',
n:0,
m:0
},
personal:{
//=>以合并时候指定的属性名为主,作为最后划分管理的名字
}
}

1
2
3
4
5
6
7
8
import { combineReducers } from 'react';
import vote from './vote';
// import personal from './personal';

let reducer = combineReducers({
vote
})
export default reducer;

vote

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import * as TYPE from '../action-types';
/*
* 1. 如果REDUX中原有的状态不存在,我们会设置一个初始值
*/

export default function vote(state={
title: '',
n: 0,
m: 0
},action){
switch(action.type){
case TYPE.VOTE_SUPPORT:
state = {...state,n:state.n + 1}
break;
case TYPE.VOTE_AGAINST:
state = {...state, m: state.m + 1};
break;
case TYPE.VOTE_INIT:
//=>初始化的时候ACTION行为对象中可能不仅有TYPE,而且还有其它需要初始化的信息值,例如:{TYPE:...,TITLE:xxx,N:xx,M:xx...}
/*state = {...state};
for (let attr in action) {
if (action.hasOwnProperty(attr)) {
if (attr === 'type') continue;
state[attr] = action[attr];
}
}*/
let {title = '', n = 0, m = 0} = action;
state = {...state, title, n, m};
break;
}
}

-------------本文结束感谢您的阅读-------------