通过实现一个 tab 切换功能了解 Redux

本文深入探讨了Redux如何解决React中非层级组件通讯和状态管理问题,通过具体实例讲解了Redux在React项目中的实践,包括状态集中管理和组件间状态同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

对于前端开发来说,Redux 这个概念一定不会陌生。但是很少有人对它非常熟悉,或者说对它理解透彻。在程序界,或者机器语言界,对于新技术,或者工具,或者语法的理解。莫过于从两个角度出发。一、思考它的作用;二、实践,通过它去解决实际问题。如果这两点做到了,对它的理解基本就达成了。以下就是通过思考 Redux 的用途和实际案例来了解 Redux。

一、Redux 解决了什么核心问题

首先明白一点,Redux 跟 React 是没有任何关联的,只不过在 React 中使用 Redux 的场景最频繁。在使用的过程中,需要下载 redux 模块和 react-redux 模块,其中 redux 是独立存在的,而 react-redux 是为了在 react 中使用 redux 做的桥接。

既然 Redux 在 React 中使用得最频繁,那么 Redux 在 React 中到底扮演着什么样的角色,起到什么样的作用呢。
我们都知道 Redux 是一个状态管理工具,而在 React 框架中, 数据流动不是很方便,只能父子组件,或者兄弟组件的通讯是比较方便的,没有层级关系的组件之间想要通讯非常麻烦,更重要的是,React 内部没有提供统一的状态管理机制。

通过以上分析,我们梳理出 redux 在 react 中解决的问题是:
1. 非层级关系组件之间的通讯;
2. 提供统一集中的状态管理工具。

二、实例说明

在 react 中封装一个 tab 切换组件。
现在假设一个场景,切换到第三个 tab 检测到没有登录,所以跳转到登录页面。登录成功之后返回到第二个 tab 页。
功能1:点击对应的 tab,改变其样式,并切换到对应的内容页。
在这里插入图片描述
功能2:点击到第三个 tab,检测到未登录,跳转到登录页。
在这里插入图片描述
功能3:点击登录页内容,跳转到第二个 tab 页。
在这里插入图片描述

三、实例代码

tabs.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import activeAction from './activeKeyAction';
import '../css/common.css';
class Tabs extends Component {
    constructor(props) {
        super(props);
    }
    componentDidMount(){
        self.slideWidth = window.innerWidth/this.props.children.length;
        const {dispatch,changeReducer} = this.props;
        if(changeReducer.activeKey == ''||changeReducer.activeKey == undefined){
            dispatch(activeAction(this.props.activeKey));
        }
        this.refs.line.style.width = self.slideWidth;
        this.refs.line.style.transform = "translateX("+ self.slideWidth * (changeReducer.activeKey-1) +"px)";
        this.refs.line.style.transition = "transform 0s";
    }
    changeTab(key,index) {
        const {dispatch, changeActive} = this.props;
        this.refs.line.style.transform = "translateX("+ self.slideWidth * index +"px)";
        this.refs.line.style.transition = "transform .3s";
        dispatch(activeAction(key));
        if (changeActive) {
            changeActive(key);
        };
    }
    render() {
        const {changeReducer} =this.props;
        console.log(changeReducer);
        return (
            <div>
                <div className="tabs">
                    <div className="line" ref="line"></div>
                    {this.props.children.map((item,index)=>{
                        return(<div style={{color:item.key==changeReducer.activeKey?'red':''}} onClick={()=>this.changeTab(item.key,index)}>
                            {item.props.label}
                        </div>)
                    })}
                </div>
                {this.props.children.map((item,index)=>{
                    if(item.key==changeReducer.activeKey){
                        return(<div>{item.props.children}</div>)
                    }else {
                        return null
                    }
                })}
            </div>
        )
    }
};
export default connect((state) => {
    const {changeReducer} = state;
    return {
        changeReducer,
    }
})(Tabs);

tabPane.js

import React, {Component} from 'react';
export default class TabPane extends Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <div>{this.props.children}</div>
            </div>
        )
    }
};

index.js

import React, {Component} from 'react';
import Tabs from './tabs';
import TabPane from './tabPane';
import One from './One';
import Two from './Two';
import Three from './Three'
export default class Index extends Component {
    constructor(props) {
        super(props);
    }
    goNext(key) {
        if (key == "3") {
            this.props.history.push({pathname: 'login'});
        }
    }
    render() {
        return (
            <Tabs activeKey="1" changeActive={(key) => {
                this.goNext(key)
            }}>
                <TabPane label="tab1" key="1"><One/></TabPane>
                <TabPane label="tab2" key="2"><Two/></TabPane>
                <TabPane label="tab3" key="3"><Three/></TabPane>
            </Tabs>
        )
    }
};

login.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import activeAction from './activeKeyAction';
class Login extends Component {
    goNext(){
        const {dispatch} = this.props;
        dispatch(activeAction("2"));
        this.props.history.push({pathname: 'index'});
    }
    render(){
        return <div className="login"  onClick={()=>this.goNext()}>我是登陆页面,点我跳到第2个tab页</div>
    }
}
export default connect((state) => {
    const {changeReducer} = state;
    return {
        changeReducer,
    }
})(Login);

四、示例分析

在本案例中,实现 tab 切换功能很容易。但是要从登录页跳转回第二个 tab 页面。如果不用 Redux,实现的步骤是:

  1. 跳转到 index 页面,携带需要切换的参数过去;
  2. 在 this.state 中添加变量接收这个参数;
  3. 将这个变量通过 props 传到父组件中;
  4. 父组件接收参数。

但是如果使用 Redux ,则只需要跳转到 index 页面,然后通过 dispatch 分发状态即可。因为所有的状态集中在顶层,只要修改了状态,则其他地方都会相应地发生改变。
在这里插入图片描述

五、总结

  1. Redux 的核心功能就是状态管理,将所有的状态集中在顶层统一管理。这样一来,一旦局部发生变化,其他使用到该变量的地方也会相应发生改变。
  2. React 中的组件通讯传值,只能通过层层传递的形式,这就意味着组件之间需要使用变量接收,然后根据业务逻辑做判断。所以正好缺少像 Redux 这样的状态管理工具。
  3. 学习 Redux 的时候有这样一句话,如果你在考虑是否需要使用 Redux ,那么你最好不要使用它。这句话的意思是说 Redux 只是用在需要使用的场合,比如跨组件通讯,跨组件修改状态等等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值