Redux拓展

reducer拓展

  路由模块也提供了一个reducer,所以整个应用程序就有了两个reducer

  一个是路由reducer 一个是自定义reducer

  为了使用多个reducer, redux提供了combineReducers方法,可以合并多个reducer

  参数是对象 key 命名空间 value reducer方法

  combineReducers功能类似于vuex中的modules: 切割store

  因为store中数据存储在state,本质上是对state的切割,因此只有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};

// reducer
function reducer(state = 0, action ) {
    switch(action.type) {
        case ADD_NUM:
            state += action.data;
            break;
        case DEL_NUM:
            state -= action.data;
            break;
        default:;
    }
    return state;
}

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}</h1>
                {/* 路由导航 */}
                <Link to="/">Home</Link>
                <Link to="/list/1">List</Link>
                <Link to="/detail/1">detail</Link>
                {/* <a href=""></a>定义hash策略不能使用 */}

            </div>
        )
    }
}
class Home extends Component {
    render() {
        console.log('home', this.props);
        return (
            <div>
                <h2>home part</h2>
            </div>
        )
    }
}
class List extends Component {
    render() {
        console.log('list', this.props);
        return (
            <div>
                <h2>list part</h2>
            </div>
        )
    }
}
class Detail extends Component {
    render() {
        console.log('detail', this.props);
        let {history, dispatch} =  this.props
        return (
            <div>
                <h2 onClick={e => dispatch(delNum2)}>detail part</h2>
                <hr/>
                <Demo history={history} dispach={dispatch}></Demo>
            </div>
        )
    }
}
class Demo extends Component {
    render() {
        console.log('demo', this.props);
        return (
            <div>
                <h2>demo part</h2>
            </div>
        )
    }
}
// 拓展高阶函数
let deal = connect(
    state =>({state}),
    dispatch =>({dispatch})
)

let DealApp = deal(App)

// 3.使用withRouter方法拓展高阶组件
let RouterApp = withRouter(App);
// 高阶组件可以一直拓展
let RouteDealApp = withRouter(DealApp);
// 拓展store
let DealDetail = deal(Detail);
// hash策略
render(
    <HashRouter>
        {/* provider在HashRouter里面外面都可 */}
        <Provider store={store}>
            {/* <App></App> */}
            {/* 拓展store */}
            {/* <DealApp></DealApp> */}
            {/* 拓展路由数据 */}
            {/* 1 */}
            {/* <Route path="/" component={DealApp}></Route> */}
            {/* 2 */}
            <RouteDealApp></RouteDealApp>
        </Provider>
       
    </HashRouter>
    , app)
// path策略, 修改hash不好使, 要搭建服务器修改地址
// render(
//     <BrowserRouter>
//         <App></App>
//     </BrowserRouter>
//     , app)
复制代码

 

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>
        )
    }
}
复制代码

 

 

 

  

 

  

  

posted @   子悔君  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示