react中的redux

一、redux简介

             官网称之为 JS 应用的状态容器,提供可预测的状态管理,并且可以与前端三大框架搭配,但是vue中有自己团队的vuex,一般与react配合使用,在我个人理解为,这可以提高数据可用性,当同一条数据在多个组件中都要调用时,这个时候就可以用状态容器进行存储调用或者对改状态进行操作

二、根据原理图进行解析

ReactComponents:当前需要使用状态管理的组件,在组件中需要引入store,通store.getState()获取state值,通过ActionCreators进行像store发送改变状态的内容

ActionCreators:用dispatch通知store要改变,action两个值:type(类型,根据type来判断如何加工数据),data(需要处理的值)

Store:存放处理好的数据。可以通过接收到新的dispatch像reducers派发更新任务

Reducers:根据接收到的任务,进行对state的改变,接收两个参数:previousState(前一个值),action就是dispatch中的那个参数,再根据type类型判断如何操作,最后把新的状态返回到store

如图

示例

下载npm install redux 在redux文件夹下

 创建store.js

/* 
	该文件专门用于暴露一个store对象,整个应用只有一个store对象
*/

//引入createStore,专门用于创建redux中最为核心的store对象
import {createStore} from 'redux'
//引入为Count组件服务的reducer
import countReducer from './reducers/count.js'
//暴露store
export default createStore(countReducer)

 创建action文件夹,在该文件夹下创建count.js

/* 
	该文件专门为Count组件生成action对象
*/

//同步action,就是指action的值为Object类型的一般对象
export const increment = data => ({type:'increment',data})
export const decrement = data => ({type:'decrement',data})

 创建reducer文件夹,在该文件夹下创建count.js

/* 
	1.该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数
	2.reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)
*/

const initState = 0 //初始化状态
export default function countReducer(preState=initState,action){
	// console.log(preState);
	//从action对象中获取:type、data
	const {type,data} = action
	//根据type决定如何加工数据
	switch (type) {
		case 'increment': //如果是加
			return preState + data
		case 'decrement': //若果是减
			return preState - data
		default:
			return preState
	}
}

最后就是在component组件中调用

import React, { Component } from 'react'
//引入store,用于获取redux中保存状态
import store from '../../redux/store'
//引入actionCreator,专门用于创建action对象
import {
	createIncrementAction,
	createDecrementAction
} from '../../redux/actions/count'

export default class Count extends Component {

	state = {carName:'奔驰c63'}

	//加法
	increment = ()=>{
		const {value} = this.selectNumber
		store.dispatch(createIncrementAction(value*1))
	}
	//减法
	decrement = ()=>{
		const {value} = this.selectNumber
		store.dispatch(createDecrementAction(value*1))
	}
	render() {
		return (
			<div>
				<h1>当前求和为:{store.getState()}</h1>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.decrement}>-</button>&nbsp;
			</div>
		)
	}
}

注意,此时状态是改变了,但是页面没有跟新

可以 通过subscribe订阅监听store中值的改变,在利用react中的setState特性驱动页面更新,如下

componentDidMount(){
	//检测redux中状态的变化,只要变化,就调用render
	 store.subscribe(()=>{
	  this.setState({})
	})
} 

如果是异步加载,需要下载redux-thunk依赖

 首先在store中引入,在createStore第二个参数中添加 applyMiddleware(thunk)

import {createStore,applyMiddleware} from 'redux'
import countReducer from './reducers/count.js'
//引入redux-thunk,用于支持异步action
import thunk from 'redux-thunk'
//暴露store
export default createStore(countReducer,applyMiddleware(thunk))

在action文件下的count.js中添加,在component中使用与同步的一样,只不过多了一个时间参数

//异步action,就是指action的值为函数,异步action中一般都会调用同步action
export const createIncrementAsyncAction = (data,time) => {
	return (dispatch)=>{
		setTimeout(()=>{
			dispatch(createIncrementAction(data))
		},time)
	}
}

注意:reducer中的函数都是纯函数,不能直接更改传入的值然后返回,这样页面不会跟新,需要用一个新的参数接收返回,然后返回,案例如下

import {ADD_PERSON} from '../constant'

//初始化人的列表
const initState = [{id:'001',name:'tom',age:18}]

export default function personReducer(preState=initState,action){
	// console.log('personReducer@#@#@#');
	const {type,data} = action
	switch (type) {
		case ADD_PERSON: //若是添加一个人
			//preState.unshift(data) //此处不可以这样写,这样会导致preState被改写了,personReducer就不是纯函数了。
			return [data,...preState]
		default:
			return preState
	}
}

这就是一个简单完整的demo 

三、 react-redux

               顾名思义,基于react封装的,主体操作模型如下

              1、所有的ui组件都是包裹在一个容器组件,他们是父子关系

              2、容器组件可以正常使用redux的api,而ui组件不能直接使用,容器组件会用porps的方式把redux中所保存的状态和用于操作的方法传给ui组件

               如下图

对了,react-redix是不需要subscribe来监听state的变化,能自动响应state的变化,然后重新渲染render 

基础用法如下(本用法是基于上一个redux之上的)

首先在父组件中引入store传入父组件, 为方便组件后代都能接收到store,省的在每个父组件中引入store,我就直接在最外面的最外面的index.js中用Provider处理了

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包裹App,目的是让App所有的后代容器组件都能接收到store */
	<Provider store={store}>
		<App/>
	</Provider>,
	document.getElementById('root')
)

然后编写 容器组件 和 ui组件 可以把容器组件 和 ui组件 集成在一个jsx文件中

import React, { Component } from 'react'
//引入action
import {
	increment,
	decrement
} from '../../redux/actions/count'
//引入connect用于连接UI组件与redux
import {connect} from 'react-redux'

//定义UI组件
class Count extends Component {
	//加法
	increment = ()=>{
		const {value} = this.selectNumber
		this.props.increment(value*1)
	}
	//减法
	decrement = ()=>{
		const {value} = this.selectNumber
		this.props.decrement(value*1)
	}
	render() {
		//console.log('UI组件接收到的props是',this.props);
		return (
			<div>
				<h4>当前求和为:{this.props.count}</h4>
				<select ref={c => this.selectNumber = c}>
					<option value="1">1</option>
					<option value="2">2</option>
					<option value="3">3</option>
				</select>&nbsp;
				<button onClick={this.increment}>+</button>&nbsp;
				<button onClick={this.decrement}>-</button>&nbsp;
			</div>
		)
	}
}

/*   
    1.使用connect()()创建并暴露一个Count的容器组件
    2.connect 两个参 mapStateToProps 和 mapDispatchToProps
      mapStateToProps:
       	1.mapStateToProps函数返回的是一个对象;
	    2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	    3.mapStateToProps用于传递状态
      mapDispatchToProps:
	   1.mapDispatchToProps函数返回的是一个对象;
	   2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value
	   3.mapDispatchToProps用于传递操作状态的方法
*/
export default connect(
	state => ({
		count:state
	}),
	{increment,decrement} //传入action
)(Count)

最后

可以把所有的reduce汇众到一个文件,然后传入combineReducers函数,在引入store中,这样就可以用state.count 或某一个值得到不同的数据,替代原先的countReducer

在reducer文件夹下新建 index.js文件

/* 
	该文件用于汇总所有的reducer为一个总的reducer
*/
//引入combineReducers,用于汇总多个reducer
import {combineReducers} from 'redux'
//引入为Count组件服务的reducer
import count from './count'
//引入为Person组件服务的reducer
import persons from './person'

//汇总所有的reducer变为一个总的reducer
export default  combineReducers({
	count,
	persons
})

猜你喜欢

转载自blog.csdn.net/qq_45689385/article/details/124390603
今日推荐