redux通信和react-redux通信

flux

Flux 是一种架构思想,专门解决软件的结构问题。它跟MVC架构是同一类东西,但是
更加简单和清晰。Flux存在多种实现(至少15种)

https://github.com/voronianski/flux-comparison

redux是flux的一种实现

Redux

Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树
(state对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,
一个新的对象就会被创建(使用actions和reducers),这样就可以进行数据追踪,实现时
光旅行。

  • 管理状态,非父子通信

  • 状态快照,数据缓存,减少服务器压力,提高用户体验

redux介绍及设计和使用的三大原则

  • state 以单一对象存储在store中
  • state只读 (每次都返回新的对象)
  • 使用纯函数reduce执行state更新

下载

cnpm intsall --save redux

主要利用发布者订阅者模式

创建store对象

import {
    
    createStore} from 'redux'  //create方法创建一个store对象

//接收两个参数一个是老对象的状态,一个是发布者传过来的对象
//必须满足纯函数的写法 深复制老状态一份在改变新状态返回新状态

const reducer = (prevState={
    
    
    isCollapsed:false
},action) =>{
    
    
    var newstate = {
    
    ...prevState}  //深复制老状态一份
    newstate.isCollapsed =  action.payload
    return newstate

    //console.log(action);

}


const store = createStore(reducer)

export default store

发布者传东西的那个组件

import store from '../../redux/store';

 store.dispatch({
    
    
            type:"MySideMenuCollapsed",
            payload:isCollapsed
        })

一旦dispatch触发就会把当前对象传给store,store借助reducer修改

扫描二维码关注公众号,回复: 11933092 查看本文章

订阅者 (接收东西的那个组件)

import store from '../../redux/store'

                
 componentDidMount() {
    
    
        store.subscribe(()=>{
    
    
            // console.log("接收到的值",store.getState())
            this.setState({
    
    
                collapsed:store.getState().isCollapsed
            })
        })
    }



需要注意在发布的时候type属性必须传,因为如果有许多组件要同时修改同一个状态的话这个时候会混淆 传了type时候可以作出判断

异步

middleware中间件 解决异步处理

  • redux-thunk
  • redux-promise

下载

cnpm install --save redux-thunk redux-promise

redux-thunk

可以让action返回一个函数 它会会传过来一个dispatch形参 自己决定什么时候发送action

    actionCreate = ()=>{
    
    
        return (dispatch)=>{
    
    
            axios.get("http://localhost:8000/roles").then(res => {
    
    
                // console.log(res.data)
                //自己决定什么时候发送
                dispatch({
    
    
                    type:"SetRoleList",
                    payload:res.data
                })    
            })
        }
import {
    
    createStore,applyMiddleware} from 'redux'  //create方法创建一个store对象

import reduxThunk from 'redux-thunk'

const reducer = (prevState={
    
    
    isCollapsed:false,  //管理侧边栏的隐藏和显示
    roleList:[]   //缓存role里面的列表
},action) =>{
    
    

    let {
    
    type,payload} = action
    switch(type){
    
    
        case "MySideMenuCollapsed":
            var newstate = {
    
    ...prevState}  //深复制老状态一份
            newstate.isCollapsed =  action.payload
            return newstate
        case "SetRoleList":
            var newstate = {
    
    ...prevState}  
            newstate.roleList = payload
            return newstate
        default:
            return prevState

    }

    //console.log(action);

}

const store = createStore(reducer,applyMiddleware(reduxThunk))
//创建store,顺便应用中间件thunk,如果action是函数我来处理


export default store

一旦store中的roleList发生变化那么store.subscribe(()=>{})就会触发所以为了避免第一开始没有值也需要订阅一次

        this.unscribe = store.subscribe(()=>{
    
    
            // console.log("请求结束",store.getState().roleList);
            this.setState({
    
    
                datalist:store.getState().roleList
            })
        }) 

同时在销毁的过程中要解除订阅

componentWillUnmount(){
    
    
        this.unscribe() //取消订阅
    }

redux-promise


import reduxPromise from 'redux-promise'

const store = createStore(reducer,applyMiddleware(reduxThunk,reduxPromise))
//创建store,顺便应用中间件thunk,如果action是函数我来处理
// 创建store,顺便应用中间件redux-promise,如果action 是promise,我来处理

dispatch 出去的action对象可以是promise对象则

 actioncreate = ()=>{
    
    
       
        return  axios.get("http://localhost:8000/rights").then(res=>{
    
    
                return {
    
    
                    type:"SetRightList",
                    payload:res.data
                }
            })
       
        }

在你dispatch的时候.then可以访问到发送完成之后的promise状态

    componentDidMount() {
    
    
        // axios.get("http://localhost:8000/rights").then(res=>{
    
    
        //     // console.log(res.data);
        //     this.setState({
    
    
        //         datalist:res.data
        //     })
        // })
        if(store.getState().rightList.length===0){
    
    
            store.dispatch(this.actioncreate()).then(data=>{
    
    
                // console.log(data);
                this.setState({
    
    
                    datalist:data.payload
                })
            })
        }else{
    
    
            console.log("使用缓存")
            this.setState({
    
    
                datalist:store.getState().rightList
            })
        }
  
    }

拆分

只能有一个syore

store只能接受一个reducer

把reducer拆开一个个的,每个reducer一个文件 combineReducer合并所有的reducer

const collapsedReducer = (prevState=false,action)=>{
    
    
    // console.log(action)
    // “修改状态”
    let {
    
    type,payload} = action
    switch(type){
    
    
        case "MySideMenuCollapsed":
            return payload
        default:
            return prevState
    }

}// 只要状态已返回, 自动同步了
export default collapsedReducer
const rightListReducer = (prevState=[],action)=>{
    
    
    // console.log(action)
    // “修改状态”
    let {
    
    type,payload} = action
    switch(type){
    
    
    
        case "SetRightList":
            var newstate = [...prevState,...payload]
            return newstate
        default:
            return prevState
    }

}// 只要状态已返回, 自动同步了
export default rightListReducer

利用combineReducers合并reducers

import {
    
    createStore,applyMiddleware,combineReducers} from 'redux' //createStore 方法创建一个store对象
import reduxThunk from 'redux-thunk'
import reduxPromsie from 'redux-promise'
import roleListReducer from './reducers/roleListReducer'
import rightListReducer from './reducers/rightListReducer'
import collapsedReducer from './reducers/collapsedReducer'
//创建一个reducer,“修改状态” (接收老状态,修改的值, 深复制之后, 再返回一个新的状态)
//合并子 reducer
const reducer = combineReducers({
    
    
    isCollapsed:collapsedReducer,
    roleList:roleListReducer,
    rightList:rightListReducer
})

/*
    reducer保证是纯函数 --函数式

    //1. 对外界没有副作用的函数
    //2. 同样的输入,得到同样的输出

    不是纯函数
    //var myname ="kerwin"
    // function test(){
    //     myname="xiaoming"
    // }
    // test()

    //纯函数
    // var myname ="kerwin"
    // function test(myname){
    //     myname="xiaoming"
    // }
    // test(myname)

    //不纯
    var obj = {myname:"kerwin"}
    function test(obj){
        obj.myname = "xiaoming"
    }
    test(obj)

    //纯
    var obj = {myname:"kerwin"}
    function test(obj){
        var newobj = {...obj}
        newobj.myname = "xiaoming"
    }
    test(obj)
*/

// store,只能接受一个reducer
// app开发 只能有一个store
// 轮船运火车 (reducer拆开一个个, 每个reducer一个文件, combineReducce(合并所有reducer))


const store = createStore(reducer,applyMiddleware(reduxThunk,reduxPromsie))
// 默认 action 只能是普通对象 {type:""}
// 创建store,顺便应用中间件thunk,如果action 是函数,我来处理
// 创建store,顺便应用中间件redux-promise,如果action 是promise,我来处理

export default store

redux dev-tools

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(reducer,composeEnhancers(applyMiddleware(reduxThunk,reduxPromsie)))

react-redux

需要有一个高阶组件connect包裹发布者和订阅者

这样就不需要子组件发布和订阅了全部交给高阶组件

但是由于高阶组件无法直接获得store所以最外层需要一个provider来传给它

首先在项目最外层用provider组件把他包裹起来把store传进去

import store from ‘./redux/store’

class App extends Component{
    
    
  render(){
    
    
    return (
      <Provider store={
    
    store}>
        <BlogRouter/>
      </Provider> 
    )
  }
}

import React, {
    
     Component } from 'react';
import './App.css';
import BlogRouter from './router'
// import { NavLink } from 'react-router-dom'
import {
    
    Provider} from 'react-redux'
import store from './redux/store'
class App extends Component{
    
    
  render(){
    
    
    return (
      <Provider store={
    
    store}>
        <BlogRouter/>
      </Provider> 
    )
  }
}
/*
  context 跨层级的通信
*/

export default App;

然后再根据高阶组件包裹

export default connect(mapStateToProps,mapDispatchToProps)(Right)

第一个参数 mapStateToProps 获得store里面的属性的这样被包裹的子组件就有了你返回的这个属性了

const mapStateToProps=(state)=>{
    
    
    return {
    
    
        datalist:state.rightList
    }
}

```

第二个参数是用来dispatch的

```
const mapDispatchToProps = {
    
    
    setList:()=>{
    
    
        //返回一个promsie对象
        return axios.get("http://localhost:8000/rights").then(res=>{
    
    
            return {
    
    
                type:"SetRightList",
                payload:res.data
            }
        })
    }
}

一旦监测到状态长度为0则发起axios请求

    componentDidMount(){
    
    
        if(this.props.datalist.length===0){
    
    
            //
            this.props.setList()
        }

猜你喜欢

转载自blog.csdn.net/yang939207690/article/details/105185463