版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/b954960630/article/details/88169187
一、实现React-Redux的过程中的DOME样式
点击Blue变为:
二、概述及源码
1、组件设计
2、主要目录结构:
- public
| - index.html
- src
| - index.js
| - components
| - react-redux.js
| - Contents.js
| - Header.js
| - ThemeSwitch.js
3、源码
注意:要先安装prop-types
(1)public文件夹下
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
(2)src文件夹下
index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Header from './components/Header';
import Content from './components/Content';
import { Provider } from './components/react-redux';
//############### redux核心函数 ###############
function createStore (reducer) {
let state = null;
const listeners = [];
const subscribe = (listener) => listeners.push(listener);
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach((listener) => listener());
}
dispatch({}); // 初始化 state
return { getState, dispatch, subscribe };
}
//############### 创建reducer、store ###############
const themeReducer = (state, action) => {
if(!state) {
return {
themeColor: 'red'
};
}
switch(action.type) {
case 'CHANGE_COLOR':
return { ...state, themeColor: action.themeColor };
default:
return state;
}
}
const store = createStore(themeReducer);
//#####################################################
class Index extends Component {
render() {
return (
<div>
<Header />
<Content />
</div>
)
}
}
ReactDOM.render(
<Provider store={store}>
<Index />
</Provider>,
document.getElementById('root')
);
react.redux.js
import React, { Component } from 'react'
import PropTypes from 'prop-types'
//connect返回一个匿名函数,这个匿名函数就是高阶组件。
export const connect = (mapStateToProps, mapDispatchToProps) =>
(WrappedComponent) => {
class Connect extends Component {
static contextTypes = {
store: PropTypes.object,
}
constructor() {
super();
this.state = { allProps: {} };
}
componentWillMount() {
const { store } = this.context;
this._updateProps();
store.subscribe(() => this._updateProps());
}
_updateProps () {
const { store } = this.context;
let stateProps = mapStateToProps
? mapStateToProps(store.getState(), this.props)// 额外传入 props,让获取数据更加灵活方便
: {}; // 防止 mapStateToProps 没有传入
let dispatchProps = mapDispatchToProps
? mapDispatchToProps(store.dispatch, this.props)
: {};
this.setState({
allProps: { // 整合普通的 props 和从 state 生成的 props
...stateProps,
...dispatchProps,
...this.props
}
});
}
render () {
return <WrappedComponent {...this.state.allProps} />
}
}
return Connect;
}
;
//Provider是一个容器组件; 它还会把外界传给它的 props.store 放到 context
export class Provider extends Component {
static propTypes = {
store: PropTypes.object,
children: PropTypes.any
}
static childContextTypes = {
store: PropTypes.object
}
getChildContext () { //把外界传进来的 props.store 放到 context
return {
store: this.props.store
}
}
render () {
return (
<div>{this.props.children}</div>
)
}
}
Header.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from './react-redux';
class Header extends Component {
static propTypes = {
themeColor: PropTypes.string
};
render() {
return (
<h1 style={{ color: this.props.themeColor }}>React.js 小书</h1>
);
}
}
//告诉connect如何获取、整合状态
const mapStateToProps = (state) => {
return {
themeColor: state.themeColor
}
};
Header = connect(mapStateToProps)(Header);
export default Header;
Content.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ThemeSwitch from './ThemeSwitch';
import { connect } from './react-redux';
class Content extends Component {
static propTypes = {
store: PropTypes.string,
}
render() {
return (
<div>
<p style={{ color: this.props.themeColor }}>React.js 小书内容</p>
<ThemeSwitch />
</div>
)
}
}
//告诉connect如何获取、整合状态
const mapStateToProps = (state) => {
return {
themeColor: state.themeColor,
}
};
Content = connect(mapStateToProps)(Content);
export default Content;
ThemeSwitch.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from './react-redux';
class ThemeSwitch extends Component {
static propTypes = {
themeColor: PropTypes.string,
onSwitchColor: PropTypes.func
}
handleSwitchColor (color) {
if (this.props.onSwitchColor) {
this.props.onSwitchColor(color)
}
}
render() {
return (
<div>
<button
style={{ color: this.props.themeColor }}
onClick={() => this.handleSwitchColor('red')}>Red
</button>
<button
style={{ color: this.props.themeColor }}
onClick={() => this.handleSwitchColor('blue')}>Blue
</button>
</div>
)
}
}
//告诉connect如何获取、整合状态
const mapStateToProps = (state) => {
return {
themeColor: state.themeColor
}
};
//告诉connect如何触发 dispatch
const mapDispatchToProps = (dispatch) => {
return {
onSwitchColor: (color) => {
dispatch({ type: 'CHANGE_COLOR', themeColor: color });
},
}
};
ThemeSwitch = connect(mapStateToProps, mapDispatchToProps)(ThemeSwitch);
export default ThemeSwitch;