赞
踩
Redux 是 JavaScript 状态容器,提供可预测化的状态管理 --> 是一个专门做状态管理的js库。
redux并不是react的插件库 --> Redux 除了和 React 一起用外,还支持其它界面库(如angular, vue 等)。 它体小精悍(只有2KB–包括依赖)。
如果你不知道是否需要 Redux,那就是不需要它
只有遇到 React 实在解决不了的问题,你才需要 Redux
Redux为单一
数据源。
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一
一个 store 中。
将state、action、reducer 关联在一起;
在 Redux API 中,State指一个唯一的 state 值
Redux管理的全部数据
,通常为一个多层嵌套的对象。Action 是一个普通对象
,用来表示即将改变 state 的意图。
State 是只读的,唯一改变 state 的方法就是触发 action。它是将数据放入 store 的唯一途径。
约定俗成,action 必须拥有一个 type
属性,表示动作类型,其他属性由自己决定。
Reducer 的作用是用于描述action 如何改变 state tree。
Reducer 只是一些纯函数
,它接收先前的 state 和 action,并返回新的 state
可用于初始化状态、加工状态;
从原理图来看 compoents 、Action Creators、 Reducers、Stroe -> 表示组件、action 、reducer都是存在多个,而Stroe是唯一的。
若是仅存在一个组件,根本不需要使用redux,只需要使用组件内部状态管理就可以实现功能。
所以现在假设存在多个组件,组件的数据使用 redux 统一管理。当某个组件想要修改数据时
举一个最简单的例子
Store 是通过 createStore
方法创建的
import { createStore } from 'redux'
createStore( reducer )
import { createStore } from 'redux'
import numReducer from './numReducer'
const store = createStore( numReducer )
combineReducers
方法进行reducer合并import { createStore, combineReducers } from 'redux'
import numReduce from './numReduce'
import countReduce from './countReduce'
const reduces = {
num:numReduce,
count:countReduce
}
const store = createStore( combineReducers(reduces) )
{
num:numReduce函数的返回值,
count:countReduce函数的返回值
}
使用Action Creator 去创建Action,使用dispatch
去派发action。
action的值可以是一个对象,也可以是一个函数
对象
表示是同步
更新数据 {
type: 动作指令(String类型),
data: 操作数据
}
函数
表示是异步
更新数据// 该方法默认会将dispatch作为函数传入
(dispatch)=>{
setTimeOut(()=>{
dispatch({type:动作指令,data: 操作数据})
},0) // 使用定时器模拟异步操作
}
export const addAction = data => ({type:INCREMENT,data})
import {addAction} from '../../../store/action.js
import store from '../../../store'
// 派发
store.dispatch(addAction( value ))'
export const addActionAsync = (data, time) =>{
return (dispatch)=>{
setTimeout(()=>{
dispatch({type:'add',data})
},time)
}
}
import {addActionAsync} from '../../../store/action.js
import store from '../../../store'
// 派发
store.dispatch(addActionAsync( value ))'
当使用dispatch去派发action时,在Store会接收到-> Stroe会去查看action的类型
若是类型为一个对象 -> Store会将action交给 reducer
若是类型为一个函数 -> 会报错
希望得到的值为一个对象。
若是希望action能够兼容值为函数的情况(也就是能够使用异步Action),需要使用一个中间件 redux-thunk
使用redux-thunk中间件后,若是类型为一个函数 -> store会调用该函数并将dispatch 方法作为参数传入(而不会交给reducer)
npm i redux-thunk
下载applyMiddleware
配置中间件import { createStore, applyMiddleware } from 'redux'
const store = createStore(
// 合并
combineReducers(reducers),
// 中间件
applyMiddleware(Thunk)
)
const init = 初始化的值 // 若是不设置,第一次渲染时默认为undefined
export default function( preState=init, action ){
const {type, data} = action
switch (type){
case type值匹配:
// 匹配后的逻辑处理
return 新的state值
...
default:
return preState
}
}
undefined
{
type:@@init... // 后面拼接随机字符
}
作用:用于获取数据
语法
import { createStore } from 'redux'
const store = createStore(reducer)
store.getState() // 获取数据
作用:用于监听redux中状态的变化,只要变化,就会走subscribe函数;
原因: redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己来;
语法
import { createStore } from 'redux'
const store = createStore(reducer)
store.subscribe(()=>{
console.log('逻辑代码-> 更新数据')
})
下面示例的编写的前提是了解redux的API的基础之上,若是没有了解过,可以结合下方的 API一起看;
现在有如上示例
若是值存储在当前组件的state中,代码如下
import React, { Component } from 'react'
export default class New extends Component {
state = { num: 0 }
render() {
const { num } = this.state
return (
<div>
{num}
<select ref={this.getref}>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<button onClick={()=>{this.calculate('increment')}}>+</button>
<button onClick={()=>{this.calculate('decrement')}}>-</button>
<button onClick={()=>{this.calculate('incrementIfOdd')}}>和为基数再加</button>
<button onClick={()=>{this.calculate('incrementAsync')}}>异步加</button>
</div>
)
}
getref = (dom) => {
this.select = dom
}
calculate = (type)=>{
// 获取到select选择的值
const { value } = this.select
const { num } = this.state
switch (type){
case 'increment':
this.setState({num: num + +value})
break;
case 'decrement':
this.setState({num: num - +value})
break;
case "incrementIfOdd":
if(num % 2 != 0){
this.setState({num: num + +value})
}
break;
case 'incrementAsync':
setTimeout(()=>{
this.setState({num: num + +value})
}, 100)
}
}
}
使用命令npm install --save redux
下载redux
import { createStore ,combineReducers,applyMiddleware} from 'redux'
import reducers from './reduces'
import Thunk from 'redux-thunk'
export default createStore(
combineReducers(reducers), // 合并reducer
applyMiddleware(Thunk) // 配置中间件
)
// num默认值为0
import {INCREMENT, DECREMENT} from '../static'
export default function( preState=0, action ){
const {type, data} = action
switch (type){
case INCREMENT:
return preState + data
case DECREMENT:
return preState - data
default:
return preState // 初始化的时候type为 @@init...
}
}
// 将所有定义的数据发导入到这个对象中然后返回
import numReduce from './num'
const reducers = {
num: numReduce // 这个值将会作为创建的state中数据的属性名‘num’
};
export default reducers;
// action可以是一个对象 也可以是一个函数
// 若是action 为一个对象表示同步更新数据,action为一个函数表示异步更新数据
import {INCREMENT, DECREMENT} from '../static'
export const addAction = data => ({type:INCREMENT,data})
export const decreaseAction = data => ({type:DECREMENT,data})
export const addActionAsync = (data, time) =>{
return (dispatch)=>{
setTimeout(()=>{
dispatch(addAction(data))
},time)
}
}
import { addAction, decreaseAction, addActionAsync } from './numAction'
export {
addAction,
decreaseAction,
addActionAsync
}
动作指令
// 指令
export const INCREMENT = 'increment' // 加法运算
export const DECREMENT = 'decrement' // 减法运算
由于很多开发者都喜欢在react中使用redux, Facebook就开发了 react-redux。
react-redux将组件分为 容器组件
和UI组件
connect用于创建一个容器组件
import {connect} from 'react-redux';
export default connect(function1,function2)(UI组件)
connect为一个函数
connect(
state=> {
return 对象 // return的对象的key ,value将添加在UI组件的props中
},
dispatch =>{
return 对象 // return的对象的key ,value将添加在UI组件的props中
}
)
参数1(mapStateToProps): 是一个回调函数
参数2(mapDispatchToProps): 是一个回调函数
返回值:connect函数的返回值也是一个函数
注意点:在使用容器组件时需要将 store作为prop传入
<Count stroe={ store }/>
在UI组件中接收-> 在props中除了接收 connect中接收的两个方法的返回值还有默认的store的属性和方法
若是我们有多个组件 ,每次都需要在容器组件传递 store,而且若是组件不是普通组件而是路由组件还不好传递,此时就可以使用Provider
组件
// [1] 引入组件
import { Provider } from 'react-redux'
import store from './store'
// [2] 包裹跟组件
<Provider store={store}>
<App/>
</Provider>
Provide组件会去查看项目里哪些组件为容器组件 将 store 传递
redux是 redux只负责管理状态,至于状态的改变驱动着页面的展示是需要我们自己控制的
若是使用了react-redux,就不需要自己监听了,当状态改变时会自动渲染对应的UI组件
使用命令 npm i react-redux
下载react-redux;
对于上面例子的改进
import React, { Component } from 'react'
import {addAction, decreaseAction, addActionAsync} from '../../../store/actions/index'
import {connect} from 'react-redux'
class New extends Component {
render() {
const { numReduce } = this.props
return (
<div>
{numReduce}
<select ref={this.getref}>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<button onClick={()=>{this.calculate('increment')}}>+</button>
<button onClick={()=>{this.calculate('decrement')}}>-</button>
<button onClick={()=>{this.calculate('incrementIfOdd')}}>和为基数再加</button>
<button onClick={()=>{this.calculate('incrementAsync')}}>异步加</button>
</div>
)
}
getref = (dom) => {
this.select = dom
}
calculate = (type)=>{
// 获取到select选择的值
const { value } = this.select
const { numReduce, add, decrease, addAsync} = this.props
switch (type){
case 'increment':
add( +value )
break;
case 'decrement':
decrease( +value )
break;
case "incrementIfOdd":
if(numReduce % 2 != 0){
add( +value )
}
break;
case 'incrementAsync':
addAsync( +value , 2000 )
}
}
}
export default connect(
state => {
return state
},
dispatch => {
return {
add(value){
dispatch(addAction( value ))
},
decrease(value){
dispatch(decreaseAction(value))
},
addAsync(value,time){
dispatch(addActionAsync(+value, time))
}
}
}
)(New)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。