Redux拓展
reducer拓展
路由模块也提供了一个reducer,所以整个应用程序就有了两个reducer
一个是路由reducer 一个是自定义reducer
为了使用多个reducer, redux提供了combineReducers方法,可以合并多个reducer
参数是对象 key 命名空间 value reducer方法
combineReducers功能类似于vuex中的modules: 切割store
因为store中数据存储在state,本质上是对state的切割,因此只有state需要添加命名空间
state拓展
在redux中,state不能修改,只能读取
在reducer中 state之所以被直接修改,因为state是值类型
值类型数据赋值相当与复制
引用类型的数据赋值相当于引用
若state是引用类型,此时操作state分为三步
1.定义结果对象 2.用state和action修改结果对象 3.将state和结果对象合并到新对象中,并返回新对象
1.先合并state 再合并结果对象,这样就可以让result中的新的属性数据覆盖state数据
2.es6提供了object.assign方法,可以用来合并多个对象
工作中 第一步就将state合并到结果对象中, 最后一步直接返回结果对象
import React, { Component } from "react"; import {render} from 'react-dom'; import {Route, BrowserRouter, HashRouter, Link, Redirect, Switch, withRouter } from 'react-router-dom'; import {createStore, combineReducers} from 'redux'; import { connect, Provider} from 'react-redux'; import {routerReducer} from 'react-router-redux' const ADD_NUM = 'ADD_NUM'; const DEL_NUM = 'DEL_NUM'; // action let addNum5 = {type: ADD_NUM, data: 5}; let delNum2 = {type: DEL_NUM, data: 2}; let defaultState = { num: 0 } // reducer // function reducer(state = defaultState, action ) { // // 1.定义结果对象 // let result = {} // switch(action.type) { // case ADD_NUM: // // 用state和action修改结果对象 // result.num = state.num + action.data; // break; // case DEL_NUM: // result.num = state.num - action.data; // break; // default:; // } // // 3.将state和结果对象合并到新对象中,并返回新对象 Object.assign()合并 // return Object.assign({}, state, result); // } // 第一步就合并state对象 function reducer(state = defaultState, action ) { // 1.定义结果对象 let result = Object.assign({}, state) switch(action.type) { case ADD_NUM: // 用state和action修改结果对象 result.num += action.data; break; case DEL_NUM: result.num -= action.data; break; default:; } // 3.将state和结果对象合并到新对象中,并返回新对象 Object.assign()合并 return result; } let store = createStore(combineReducers({ zihui: reducer, // 省略语法 当k v 相同时可省略 routerReducer })) class App extends Component { render() { console.log('app', this.props); let { match, state, dispatch} = this.props return( <div> <button onClick={e => dispatch(addNum5)}>增加5</button> {/* 1父子组件通信的方式传递数据可以传递部分数据 */} {/* App和Header父子 */} <Header match={match} state={state}></Header> <hr/> <Switch> {/* exact表示精确匹配 */} <Route path='/' component={Home} exact></Route> <Route path='/list/:page' component={List} ></Route> {/* Detail组件与App不是父子关系 不能传输数据 */} {/* <Route path="/detail/:id" component={Detail} state={state}></Route> */} <Route path='/detail/:id' component={DealDetail} ></Route> {/* 重定向 */} <Redirect from="/zihui" to="/detail/zihui"></Redirect> {/* 默认路由 */} <Route path="*" component={Home}></Route> </Switch> </div> ) } } class Header extends Component { render() { console.log('header', this.props); return ( <div> {/* 合并reducer后 要通过命名空间访问数据 */} <h1>header part - {this.props.state.zihui.num}</h1> {/* 路由导航 */} <Link to="/">Home</Link> <Link to="/list/1">List</Link> <Link to="/detail/1">detail</Link> {/* <a href=""></a>定义hash策略不能使用 */} </div> ) } }
action拓展
redux中action两类
同步action:
静态action: 对象 type data
动态action 方法 执行并传递数据
返回 action对象 并存储参数数据
动态action与拓展属性方法区别
拓展属性方法灵活传递数据 但会污染组件的属性对象
动态action灵活传递数据,不会污染组件的属性对象,工作中常用
异步action 方法 参数:传递的数据 返回值是方法
第一个参数 dispatch(常用) 第二个参数 getState
在方法中,做异步事件, 异步结束后,再发布同步消息
中间件
redux默认不支持异步action,象使用异步action要为redux安装中间件插件
redux模块提供了applyMiddleware方法
参数是中间件
返回时是一个方法, 用来拓展createStore方法
返回值是一个新的createStore方法
该方法创建的store就支持异步action
异步action中间件插件redux-thunk
import React, { Component } from "react"; import {render} from 'react-dom'; import {Route, BrowserRouter, HashRouter, Link, Redirect, Switch, withRouter } from 'react-router-dom'; import {createStore, combineReducers, applyMiddleware} from 'redux'; import { connect, Provider} from 'react-redux'; import {routerReducer} from 'react-router-redux' // 引入中间件 import ReduxThunk from 'redux-thunk'; // 引入axios发送异步请求 import Axios from 'axios'; const ADD_NUM = 'ADD_NUM'; const DEL_NUM = 'DEL_NUM'; const SAVE_DATA = 'SAVE_DATA' // 同步action 静态和动态 // 静态action let addNum5 = {type: ADD_NUM, data: 5}; let delNum2 = {type: DEL_NUM, data: 2}; // 动态action // let addNum = data => { // return {type: ADD_NUM, data } // } let addNum = data => ({type: ADD_NUM, data }) // 异步action同动态action是一个方法 返回值是方法 let savaData = data => ({type: SAVE_DATA, data}) // 需要安装中间件 // let getData = (...args) => { // // 100, 200 // // console.log('out' , args); // return(dispatch, ...args) => { // // console.log('inner', args); // Axios.get('/data/demo.json') // // 解构data // .then(({data}) => { // // console.log(data); // dispatch(savaData(data.title)) // }) // } // } // 简写 let getData = (...args) => dispatch => Axios.get('/data/demo.json') .then(({data}) => { dispatch(savaData(data.title)) }) let defaultState = { num: 0 } // reducer // 第一步就合并state对象 function reducer(state = defaultState, action ) { // 1.定义结果对象 let result = Object.assign({}, state) switch(action.type) { case ADD_NUM: // 用state和action修改结果对象 result.num += action.data; break; case DEL_NUM: result.num -= action.data; break; // 存储消息 case SAVE_DATA: result.data = action.data; break; default:; } // 3.将state和结果对象合并到新对象中,并返回新对象 Object.assign()合并 return result; } // let store = createStore(combineReducers({ // zihui: reducer, // // 省略语法 当k v 相同时可省略 // routerReducer // })) // 给store拓展异步action功能 // let dealStore = applyMiddleware(ReduxThunk); // 拓展新的createStore // let newCreatStore = dealStore(createStore); // 创建新的store // let store = newCreatStore(createStore); // 三步合并为一步 let store = applyMiddleware(ReduxThunk)(createStore)(combineReducers({ zihui: reducer, // 省略语法 当k v 相同时可省略 routerReducer })) class App extends Component { render() { console.log('app', this.props); let { match, state, dispatch} = this.props return( <div> <button onClick={e => dispatch(addNum5)}>增加5</button> <button onClick={e => dispatch({type: ADD_NUM, data: 10})}>增加10</button> {/* 动态action */} <button onClick={e => dispatch(addNum(20))}>增加20</button> {/* 异步action,发送请求获取数据 需要服务器 */} <button onClick={dispatch(getData(100, 200))}>获取数据</button> {/* 1父子组件通信的方式传递数据可以传递部分数据 */} {/* App和Header父子 */} <Header match={match} state={state}></Header> <hr/> <Switch> {/* exact表示精确匹配 */} <Route path='/' component={Home} exact></Route> <Route path='/list/:page' component={List} ></Route> {/* Detail组件与App不是父子关系 不能传输数据 */} {/* <Route path="/detail/:id" component={Detail} state={state}></Route> */} <Route path='/detail/:id' component={DealDetail} ></Route> {/* 重定向 */} <Redirect from="/zihui" to="/detail/zihui"></Redirect> {/* 默认路由 */} <Route path="*" component={Home}></Route> </Switch> </div> ) } } class Header extends Component { render() { console.log('header', this.props); return ( <div> {/* 合并reducer后 要通过命名空间访问数据 */} <h1>header part - {this.props.state.zihui.num} - {this.props.state.zihui.data}</h1> {/* 路由导航 */} <Link to="/">Home</Link> <Link to="/list/1">List</Link> <Link to="/detail/1">detail</Link> {/* <a href=""></a>定义hash策略不能使用 */} </div> ) } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具