redux
redux是第三方的一个状态管理工具。
先下载npm install --save redux
,然后给store对象一个存放位置。
Redux-创建store的createStore:https://www.jianshu.com/p/53d010fb76d8
一、基础拆分过程
1、数据获取-----------------------
先看下 redux使用、创建基础流程。
>>store.js
// 1、引用createStore,创建store对象
import {createStore} from "redux"
// 4、创建数据
let obj={
name:"sky",
age:18
}
// 5、创建reducer 使用纯函数的方式来对数据和修改操作进行关联
// reducer作为一个桥梁 ,负责响应action并修改数据
let reducer=(state=obj,action)=>{
return state
}
// 2、创建store对象,通过reducer将数据与操作关联起来
let store=createStore(reducer)
// 3、暴露store对象
export default store
全局中取数据,通过store.getState().xxx
>>index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// 引入store.js
import store from "./store/store.js"
// 然后在后台打印这个全局下的store
console.log(store);
console.log(store.getState().name);
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.unregister();
组件中取数据,跟全局的方法一样吧,都是store.getState().xxx
>>Bro1.jsx
import React, { Component } from 'react'
// 也是先引入
import store from "../store/store.js"
export default class Bro1 extends Component {
constructor(props) {
super(props)
this.state = {
// 获取store里的数据
text: store.getState().name
}
}
render() {
return (
<div>
<h4>I'm big bro1.</h4>
<p>组件里面从store取数据:{this.state.text}</p>
</div>
)
}
}
2、数据修改-----------------------
>>Bro1.jsx
import React, { Component } from 'react'
import store from "../store/store.js"
export default class Bro1 extends Component {
constructor(props) {
super(props)
this.state = {
text: store.getState().age
}
}
update=()=>{
// 进行redux的修改 使用dispatch 来进行该修改的分发
// 若有很多修改动作,通过store.dispatch({type:"调用的任务名--全部大写"})
store.dispatch({type:"REDUX_UPDATE"})
}
componentDidMount() {
// subscribe添加一个变化监听器,每当改变store的时候就会执行
store.subscribe(()=>{
this.setState({
text:store.getState().age
})
})
}
render() {
return (
<div>
<h4>I'm big bro1.</h4>
<p>组件里面从store取数据:{this.state.text}</p>
<button onClick={this.update}>点击修改redux中的数据</button>
</div>
)
}
}
在store.js中修改reducer的任务判断
>>store.js
import {createStore} from "redux"
let obj={
name:"sky",
age:18
}
let reducer=(state=obj,action)=>{
// 因为修改会有n个操作,为了方便知道对应修改操作是哪个,
// 可以通过switch来判断多个修改任务
switch(action.type){
case "REDUX_UPDATE":
return {...state,age:state.age+1} //先用扩展运算符把state展开,当前存储的是obj,就是把obj展开
break;
default:
return state
break;
}
}
let store=createStore(reducer)
export default store
3、拆分-----------------------
(1)先把 创建数据、创建reducer两部给分离出去,单独成文件。
>>reducer.js
// 把原来的数据和任务都放到这个新建的文件中,方便管理
// 4、创建数据
let obj={
name:"sky",
age:18
}
// 5、创建reducer 使用纯函数的方式来对数据和修改操作进行关联
let reducer=(state=obj,action)=>{
switch(action.type){
case "REDUX_UPDATE":
// return {...state,age:state.age+1}
//先用扩展运算符把state展开,当前存储的是obj,就是把obj展开
return {...state,age:state.age+action.num} //num 是接收到的数据
break;
default:
return state;
break;
}
}
export default reducer
>>store.js
import {createStore} from "redux"
// 引入已经拆分出去的数据和任务 ,在reducer.js中
import reducer from "./reducer.js"
let store=createStore(reducer)
export default store
拆分开功能也是可以正常实现的。
(2)然后把用在页面组件中的任务,也给分离出去,拆分任务名与数据。(就是把原来dispatch的对象单独拿出去)
先拆分数据--------------------
>>actionType.js
let ADD=(val)=>{
return {type:"REDUX_UPDATE",num:val}
}
export {ADD}
>>Bro1.js
import React, { Component } from 'react'
import store from "../store/store.js"
// 引入拆分出去的任务名和数据
import {ADD} from "../store/actionType.js"
export default class Bro1 extends Component {
...
update=()=>{
// store.dispatch({type:"REDUX_UPDATE",num:2})
// 传过去一个num,在那边可以使用
// 使用拆分出去的任务名和数据,之前咱们传的num:2,现在也是通过ADD方法来实现
store.dispatch(ADD(3))
}
...
}
再更细一点拆分任务名,这一步看个人需要--------------------
>>acitonName.js
// 拆分任务名
export let REDUX_UPDATE="REDUX_UPDATE";
>>actionType.js
// 引入任务名
import {REDUX_UPDATE} from "./actionName"
let ADD=(val)=>{
return {type:REDUX_UPDATE,num:val}
}
export {ADD}
>>reducer.js
// 引入任务名
import {REDUX_UPDATE} from "./actionName"
let obj={
name:"sky",
age:18
}
let reducer=(state=obj,action)=>{
switch(action.type){
case REDUX_UPDATE:
return {...state,age:state.age+action.num} //num 是接收到的数据
break;
default:
return state
break;
}
}
export default reducer
二、完整拆分流程
完整的应该是把reducer合并再加上。看下面。
先新建一个文件夹storenew,然后创建一个文件storenew.js,然后把reducer独立到reducer.js里面。
>>storenew.js
import {createStore} from "redux"
import reducer from "./reducer.js"
let storenew=createStore(reducer);
export default storenew
>>reducer.js
import tryComReducer from "../compnew/tryComReducer.js"
import {combineReducers} from "redux"
// 合并分散的reducers
let reducer=combineReducers({
tryComReducer
})
export default reducer
然后咱们再新建一个compnew文件,创建一个组件tryCom.jsx,然后创建一个专属于这个组件的reducer(有点类似于vuex中的数据模块仓库 ),命名为tryComReducer.js 。
>>tryCom.jsx
import React, { Component } from 'react'
import storenew from "../storenew/storenew.js"
import { ADD } from "../storenew/actionType.js"
export default class tryCom extends Component {
constructor(props) {
super(props)
this.state = {
textname: storenew.getState().tryComReducer.name,
textage: storenew.getState().tryComReducer.age
}
}
componentDidMount() {
storenew.subscribe(() => {
this.setState({
textage: storenew.getState().tryComReducer.age
})
})
}
fun() {
storenew.dispatch(ADD(4))
}
render() {
return (
<div>
<h4>I'm 尝试store的组件.</h4>
<p>从store拿到的名字:{this.state.textname}</p>
<p>从store拿到的年龄:{this.state.textage}</p>
<button onClick={this.fun}>点击修改</button>
</div>
)
}
}
tryComReducer.js放的是分散的reducer的一个部分。最后这些分散的部分在reducer.js中进行了合并。
>>tryComReducer.js
// 数据 actions的修改操作
import {TRYCOM_ADD} from "../storenew/actionName.js"
let data = {
name: "susan",
age: 19
}
let tryComReducer = (state = data, action) => {
switch (action.type) {
case TRYCOM_ADD:
return {...state,age:state.age+action.num}
break;
default:
return state;
break;
}
}
export default tryComReducer
其中对修改操作的名字和数据进行了封装。
>>actionType.js
// 将任务名封装的这一步,按自己需要封
// 不过封的话,能够减少名字之间的耦合性
import {TRYCOM_ADD} from "./actionName.js"
export let ADD=(num)=>{
return {type:TRYCOM_ADD,num}
}
>>actionNamw.js
export let TRYCOM_ADD="TRYCOM_ADD"
涉及到的文件
总结
这个拆起来看似有点麻烦,但其实,就两大部分:redux中、组件中。
第一部分,拆store对象部分,把store对象中的源数据与动作封装到reducer.js里面,文件名随意定义。然后把分散的reducer模块合并到一个reducer.js文件中,在store创建时把这个reducer给传过去。
第二部分,就是把用在组件中的,修改store中数据的操作给封装起来。把dispatch派发动作和要给store发的参数给单独封起来,为了方便以后的维护,又把任务名也单独封起来了。