day07react中的状态管理:Redux、React-Redux、Redux-thunk

day24笔记

一、Redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理.
1.单一数据源(state)
整个应用状态,都应该被存储在单一store的对象树中。
2.只读状态
唯一可以修改状态的方式,就是发送(dispatch)一个动作(Action),通俗来讲,就是说只有getter,没有setter。
3.使用纯函数去修改状态(Reducer)
(其实就是一个函数返回{})

  • Redux 的设计思想

(1)Web 应用是一个状态机,视图与状态是一一对应的。
(2)所有的状态,保存在一个对象里面。

  • 下载方式
    npm install(i) redux
    “redux”: “^4.0.5”
  • 创建一个仓库(基本的取值过程)
//1、引入创建仓库的方法
import { createStore } from 'redux'
//2、初始化一个state状态
const initState = {
    msg: '人生若只如初见'
}
//3、创建一个 reducer纯函数 这个函数有两个参数,第一个参数是state,第二个参数是action 行动  action行动中可定有type类型
function reducer(state = initState, action) {
    switch (action.type) {
        case 'a':

            return {
                ...state
            }

        default:
            return state
    }
}
// 4、建一个仓库
const state = createStore(reducer)

//6、封装一个类似getter
export const getMsg = () => state.getState().msg
//5、暴露出当前的state
export default state
  • 修改仓库状态(index.js)
//1、引入创建仓库的方法
import { createStore } from 'redux'
//2、初始化一个state状态
const initState = {
    msg: '人生若只如初见',
    num:5
}

//7、创建一个行动,并暴露 行动action必须有一个属性叫type
/* export const changeMsgAction = (msg)=>{
    return{
        type:'changeMsg',
        msg:msg
    }
}
 */
export const changeMsgAction = (msg)=>({
    type:'changeMsg',
    msg
})
export const changeNumAction =()=>({
    type:'changeNum'
})

//3、创建一个 reducer纯函数 这个函数有两个参数,第一个参数是state,第二个参数是action 行动  action行动中可定有type类型
function reducer(state = initState, action) {
    console.log(action,'switch中的action')
    switch (action.type) {
        case 'changeMsg':
            return {
                ...state,
                msg:action.msg
            }
        case 'changeNum':
            return {
                ...state,
                num:state.num +1
            }
        default:
            return state
    }
}
// 4、建一个仓库
const store = createStore(reducer)

//6、封装一个类似getter
export const getMsg = () => store.getState().msg
export const getNum = ()=>store.getState().num
//5、暴露出当前的state
export default store
  • one.js(取值并修改状态的案例)
import React from 'react'
import Store, { getMsg,changeMsgAction,getNum } from '../../store'

class One extends React.Component {
    constructor(){
        super()
        this.state = {
            msg:'那还不如不见'
        }
    }
    //组件一加载就调取监听方法(订阅者模式subscribe)
    componentDidMount(){
        Store.subscribe(()=>{
            this.setState({})
        })
    }
    //改变state的事件
    changeMsg(msg){
        Store.dispatch(changeMsgAction(msg))
    }
    render() {
        const {msg} = this.state
        return (
            <div className="box">
                <h1>我是组件一</h1>
                <button onClick={this.changeMsg.bind(this,msg)}>我想要修改这首诗</button>
                <h1>我是直接从state中取值----{Store.getState().msg}</h1>
                <h1>取封装之后的state---{getMsg()}</h1>
                <hr/>
        <h1>当前的数量是--{getNum()}</h1>
            </div>
        )
    }
}

export default One

二、React-Redux(类的创建方式)
  • React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)
  • UI组件

只负责 UI 的呈现,不带有任何业务逻辑
没有状态(即不使用this.state这个变量)
所有数据都由参数(this.props)提供
不使用任何 Redux 的 API

  • 容器组件

负责管理数据和业务逻辑,不负责 UI 的呈现
带有内部状态
使用 Redux 的 API

  • 下载并安装 React-Redux
    npm install(i) react-redux
    “react-redux”: “^7.2.0”,

三、Redux-thunk (中间件)
  • 下载命令并安装
npm install redux-thunk

//版本号是
"redux-thunk": "^2.3.0"

四、获取动态列表案例
  • 清空创建项目
  • 准备数据,并且在浏览器中测试,数据可以获取
  • 创建组件和路由
npm i react-router-dom
  • 把一级路由创建出来并可以渲染
  • index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//引入浏览器解析路由的插件
import {BrowserRouter} from 'react-router-dom'

ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));

  • app.js
import React from 'react';
import './App.css';
import List from './components/list'
import {Switch,Route,Redirect} from 'react-router-dom'

function App() {
  return (
    <div className="App">
      <Switch>
        <Route path='/list' component={List}></Route>
        <Redirect to='/list'></Redirect>
      </Switch>
    </div>
  );
}

export default App;
  • 创建一个redux 并导出一个name(npm i redux)
//引入创建仓库的方法
import {createStore} from 'redux'
//初始化state
const initState={
    name:'李白'
}

//创建一个reducer
function reducer(state=initState,action){
    switch (key) {
        case 'a':
            return state
    
        default:
            return state
    }
}

const store = createStore(reducer)
//暴露出name数据
export const getName = ()=>store.getState().name

export default store
  • 创建一个React-redux(npm i react-redux)
  • index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//引入浏览器解析路由的插件
import {BrowserRouter} from 'react-router-dom'
//引入React-redux
import { Provider} from 'react-redux'
//全局引入Redux
import store from './store'

ReactDOM.render(<Provider store={store}><BrowserRouter><App /></BrowserRouter></Provider>, document.getElementById('root'));

  • 封装list组件
  • list.js
import React from 'react'
//应用React-redux 拆分成两部分
import { connect } from 'react-redux'
//从redux中取出你需要的数据(API)
import { getName,getList, changNameAction } from '../store'
class List extends React.Component {
    render() {
        const { name,changeName,musicList } = this.props
        console.log(musicList,'musicList')
        return (
            <div>
                <h1>这是音乐列表</h1>
                <h1>姓名:{name}</h1>
                <button onClick={changeName.bind(this,'白居易')}>点击更换名字</button>
            </div>
        )
    }
}
//定义一个函数 函数作用是从仓库中去出state值
const mapStateToProps = () => {
    return {
        name: getName(),
        musicList:getList()
    }
}
//定义一个函数 函数的作用是从仓库中(dispatch)触发action 
const mapDispatchToProps = (dispatch)=>{
    return {
        changeName:(name)=>dispatch(changNameAction(name))
    }
}
export default connect(mapStateToProps,mapDispatchToProps)(List)

  • 封装接口
  • util=>axiosConfig.js =>axios.js
//axiosConfig
import axios from 'axios'

let http  = axios.create()

http.interceptors.request.use(config=>{
    return config
})

http.interceptors.response.use(res=>{
    return res
})

export default http

//axios
import http from './axiosConfig'

let getData ={} 

//封装一个音乐列表接口
getData.getMusic = ()=>{
    return http.get('/mock/music.json')
}

export default getData

  • 仓库中异步调取接口
  • index.js(仓库)
//引入创建仓库的方法 并引用应用中间件的方法
import {createStore,applyMiddleware} from 'redux'
//引入type类型
import {CHANGE_NAME,CHANGE_LIST} from './type'
//引入redux-thunk中间件
import thunk from 'redux-thunk'
//引入封装好的接口文件
import api from '../util/axios'
//初始化state
const initState={
    name:'李白',
    list:[]
}

//修改名字
export const changNameAction =(name)=>{
    return {
        type:CHANGE_NAME,
        name
    }
}

//修改list列表的函数(同步 这段相当于mutation)
const changeList = (list)=>{
    return {
        type:CHANGE_LIST,
        list
    }
}

//导出一个获取list列表(创建一个异步函数)
export const reqListAction = ()=>{
    return (dispatch,getState)=>{
        //数据缓存
        if(getState().list.length>0){
            return
        }
        //调取音乐接口列表
        api.getMusic()
        .then(res=>{
            console.log(res,'仓库中取列表')
            return dispatch(changeList(res.data.data))
        })
        .catch(err=>{})
    }
}

//创建一个reducer
function reducer(state=initState,action){
    switch (action.type) {
        case CHANGE_NAME://修改名字
            return {
                ...state,
                name:action.name
            }
        case CHANGE_LIST://修改列表
        return {
            ...state,
            list:action.list
        }
        default:
            return state
    }
}

//导出仓库 并使用redux-thunk中间件
const store = createStore(reducer,applyMiddleware(thunk))
//暴露出name数据
export const getName = ()=>store.getState().name
//暴露出列表
export const getList = ()=>store.getState().list

export default store

  • 封装一个type模块
  • type.js(抽离出这个模块,好处一次修改多次应用)
//导出一个修改名字的类型
export const CHANGE_NAME = 'changeName'
export const CHANGE_LIST = 'changeList'


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值