空谷足音 2019-12-16
目录:
1、
2、
3、
1、一个demo,纯react实现
效果:

项目结构:

index.js
import React from ‘react‘ import ReactDOM from ‘react-dom‘ import App from ‘./components/app.jsx‘ ReactDOM.render(<App></App>, document.getElementById(‘app‘))
app.jsx
import React from ‘react‘
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
render() {
return (
<div>
<p>click {this.state.count} times</p>
<select ref={select => this.select = select}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
increment = () => {
const num = this.select.value * 1
const { count } = this.state
this.setState({ count: count + num })
}
decrement = () => {
const num = this.select.value * 1
const { count } = this.state
this.setState({ count: count - num })
}
}2、引入redux的实现
下载依赖
npm install --save redux
redux工作流程

redux核心API
使用redux改造后,项目结构:

index.js
import React from ‘react‘
import ReactDOM from ‘react-dom‘
import { createStore } from ‘redux‘
import App from ‘./components/app.jsx‘
import { counter } from ‘./redux/reducers.js‘
// 根据counter函数创建store对象
const store = createStore(counter)
// 定义渲染根组件标签的函数
const render = () => {
ReactDOM.render(
<App store={store} />,
document.getElementById(‘root‘)
)
}
// 初始化渲染
render()
// 注册(订阅)监听, 一旦状态发生改变, 自动重新渲染
store.subscribe(render)app.jsx
import React from ‘react‘
import PropTypes from ‘prop-types‘
import * as actions from ‘../redux/actions.js‘
export default class App extends React.Component {
static propTypes = {
store: PropTypes.object.isRequired,
}
render() {
return (
<div>
<p>click {this.props.store.getState()} times</p>
<select ref={select => this.select = select}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
increment = () => {
const number = this.select.value * 1
this.props.store.dispatch(actions.increment(number))
}
decrement = () => {
const number = this.select.value * 1
this.props.store.dispatch(actions.decrement(number))
}
}action-types.js
// action对象的type常量名称模块 export const INCREMENT = ‘increment‘ export const DECREMENT = ‘decrement‘
action.js
// action creator模块
import { INCREMENT, DECREMENT } from ‘./action-types.js‘
export const increment = number => ({ type: INCREMENT, number })
export const decrement = number => ({ type: DECREMENT, number })reducers.js
// 根据旧state和指定action, 处理返回一个新的state
import { INCREMENT, DECREMENT } from ‘./action-types.js‘
export function counter(state = 0, action) {
console.log(‘counter‘, state, action)
switch (action.type) {
case INCREMENT:
return state + action.number
case DECREMENT:
return state - action.number
default:
return state
}
}3、引入redux + react-redux
React-Redux的思想:将所有组件分成两大类
1) UI组件
a.只负责 UI 的呈现,不带有任何业务逻辑
b.通过props接收数据(一般数据和函数)
c.不使用任何 Redux 的 API
d.一般保存在components文件夹下
2) 容器组件
a.负责管理数据和业务逻辑,不负责UI的呈现
b.使用 Redux 的 API
c.一般保存在containers文件夹下
改造后项目结构:

index.js
import React from ‘react‘
import ReactDOM from ‘react-dom‘
import { Provider } from ‘react-redux‘
import App from ‘./containters/app.jsx‘
import store from ‘./redux/store.js‘
ReactDOM.render(
(<Provider store={store}>
<App />
</Provider>),
document.getElementById(‘root‘)
)app.jsx
/*
包含Counter组件的容器组件
*/
import React from ‘react‘
// 引入连接函数
import { connect } from ‘react-redux‘
// 引入action函数
import { increment, decrement } from ‘../redux/actions.js‘
import Counter from ‘../components/counter.jsx‘
// 向外暴露连接App组件的包装组件
export default connect(
state => ({ count: state }),
{ increment, decrement }
)(Counter)counter.jsx
/*
UI组件: 不包含任何redux API
*/
import React from ‘react‘
import PropTypes from ‘prop-types‘
export default class Counter extends React.Component {
static propTypes = {
count: PropTypes.number.isRequired,
increment: PropTypes.func.isRequired,
decrement: PropTypes.func.isRequired
}
render() {
return (
<div>
<p>click {this.props.count} times</p>
<select ref={select => this.select = select}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button onClick={this.increment}>+</button>
<button onClick={this.decrement}>-</button>
</div>
)
}
increment = () => {
const number = this.select.value * 1
this.props.increment(number)
}
decrement = () => {
const number = this.select.value * 1
this.props.decrement(number)
}
}action-types.js
// action对象的type常量名称模块 export const INCREMENT = ‘increment‘ export const DECREMENT = ‘decrement‘
actions.js
// action creator模块
import { INCREMENT, DECREMENT } from ‘./action-types.js‘
export const increment = number => ({ type: INCREMENT, number })
export const decrement = number => ({ type: DECREMENT, number })reducers.js
// 根据旧state和指定action, 处理返回一个新的state
import { INCREMENT, DECREMENT } from ‘./action-types.js‘
export function counter(state = 0, action) {
console.log(‘counter‘, state, action)
switch (action.type) {
case INCREMENT:
return state + action.number
case DECREMENT:
return state - action.number
default:
return state
}
}store.js
import { createStore } from ‘redux‘
import { counter } from ‘./reducers.js‘
// 根据counter函数创建store对象
const store = createStore(counter)
export default store