美文网首页
Redux状态管理与React-router

Redux状态管理与React-router

作者: 陈裔松的技术博客 | 来源:发表于2019-03-08 21:11 被阅读0次

    Redux状态管理

    • 概念:Redux是专注于状态管理的库
    • 组成:store,state,action,reducer
    • 安装:yarn add redux
    • 补充:不仅仅是React,在Vue和Angular中也可以使用Redux
    1,基本介绍
    • store:数据源,用于存储状态(state)
    • state:React中的状态,是只读对象,不可直接修改
    • reducer:基本函数,用于对state的业务处理
    • action:普通对象,用于描述事件的行为,改变state
    2,工作流
    • 用户的一个行为(比如鼠标点击)会触发Action
    • Action会分发(dispatch)给Reducer
    • 在Reducer中会对状态(stata)做相应的修改,并保存到数据源(STORE)中
    • 组件(Component)会监听数据源(STORE)中state的变化,从而改变页面的展示内容
    image.png
    3,调试工具安装(可选,建议安装)
    • 添加Chrome扩展程序Redux Devtools
    • 安装第三方库redux-devtools-extension:yarn add redux-devtools-extension
    4,在React中使用Redux(以切换菜单为例)
    • 安装react-redux插件:yarn add react-redux
    • 创建Action模块
    // 文件:src/redux/action/index.js
    
    // Action类型
    export const type = {
        SWITCH_MENU:'SWITCH_MENU'
    }
    
    // Action函数
    // 参数:用户点击的某个菜单名称
    // 返回值:对象,包括事件类型和用户点击的菜单名称的对象
    export function switchMenu(menuName){
        return{
            type:type.SWITCH_MENU,  // 事件类型
            menuName                // 菜单名称
        }
    }
    
    • 创建Reducer模块
    // 文件:src/redux/reducer/index.js
    
    // 引入action类型
    import { type } from './../action';
    
    // 初始化state
    const initialState = {
        menuName:'首页',
    }
    
    // 业务处理函数
    // 参数1:状态(state),参数2:动作(action)
    // 返回值:对象,是一个包括所有最新state的对象
    export default (state = initialState, action) => {
        switch (action.type) {
            // 切换菜单
            case type.SWITCH_MENU:
                return {
                    ...state,                 // 通过对象解构的方式保留原来的所有state
                    menuName:action.menuName  // 更新menuName
                }
            default:
                return {
                    ...state
                };
        }
    } 
    
    • 创建Store模块
      如果没有安装调试工具redux-devtools-extension,这样写。
    // 文件:src/redux/store/index.js
    
    // 引入reducer
    import reducer from './../reducer';
    
    // 引入createStore。这是Redux中的一个方法,用于创建一个数据源对象,保存数据
    import { createStore } from 'redux';
    
    // 导出数据源
    export default () => createStore(reducer)
    

    如果已经安装调试工具redux-devtools-extension,这样写。可以用Redux Devtools清楚地看到redux状态的变化(如果出错了,就用上一种写法,比较保险)

    // 文件:src/redux/store/index.js
    
    // 引入reducer
    import reducer from './../reducer';
    
    // 引入createStore。这是Redux中的一个方法,用于创建一个数据源对象,保存数据
    import { createStore } from 'redux';
    
    // 引入调试工具redux-devtools-extension
    import { composeWithDevTools } from 'redux-devtools-extension';
    
    // 导出数据源,可以方便地看到state变化
    export default () => createStore(reducer,composeWithDevTools())
    
    • 添加Provider作为项目的根组件,用于数据的存储
    // 文件:index.js
    
    import { Provider } from 'react-redux';      // 引入Provider组件,用于提供数据源
    import configureStore from './redux/store';  // 导入数据源创建方法
    const store = configureStore();              // 创建数据源
    
    // 用Provider组件包裹根组件Router,以提供数据源
    // 这样Router里面的所有组件,都可以从数据源中获取数据
    ReactDOM.render(
        <Provider store={store}>
            <Router />
        </Provider>,
        document.getElementById('root'));
    
    • 通过connect方法将React组件和Redux连接起来
      更新redux的状态
    import { connect } from 'react-redux';              // 引入react-redux的connect方法
    import { switchMenu } from './../../redux/action';  // 引入已经定义好的action
    
    class Sidebar extends React.Component {
        // ...省略...
        currentTitleManage = () => {
            // ...省略...
            this.props.dispatch(switchMenu(currentTitle));  // 触发switchMenu动作
            // ...省略...
        }
        // ...省略...
    }
    
    // 通过connect方法连接Sidebar组件和redux
    export default connect()(Sidebar);
    

    取得redux的状态

    import { connect } from 'react-redux';
    
    class Header extends React.Component {
        // ...省略...
        {this.props.menuName}  // 取得菜单名称
        // ...省略...
    }
    
    // 获取数据源
    const mapStateToProps = state => {
        return {
            menuName: state.menuName
        }
    }
    
    // 通过connect方法连接Header组件和redux
    export default connect(mapStateToProps)(Header);
    

    React-router

    • 安装:yarn add react-router-dom
      为什么要安装react-router-dom而不是react-router?
      因为在React Router 4.0中,react-router-dom是专门用于浏览器端的路由控制器,其中已经包含了基础路由(react-router),所有我们只需要安装react-router-dom就可以了。
    1,react-router和react-router-dom理解
    • react-router:提供了一些router的核心api,包括Router,Route,Switch等
    • react-router-dom:提供了BrowserRouter,HashRouter,Route,Link,NavLink
    2,react-router-dom核心用法
        // path:路径,component:路径对应的组件
        <Route path="/login" component={Login}/>
    
        // render:添加子路由
        // exact:精准匹配
        <Route path='/' render={()=>
            this.props.logout ? 
            (
                <Redirect to={`/login`}/>
            ) :
            (
                <Admin>
                    <Switch>
                        <Route path="/home" component={Home}/>
                        <Route exact path='/contracts/list' component={ContractList}/>
                        ...
    
    • NavLink,Link
    // NavLink:主要用于菜单导航
    
    import { NavLink } from 'react-router-dom';
    
        // 第一种写法:to地址
        <NavLink to='/home' replace>
            <span>首页</span>
        </NavLink>
    
        // 第二种写法:to对象,对象里包含一个pathname属性
        <NavLink to={pathname:'/home'} replace>
            <span>首页</span>
        </NavLink>
    
        // 第三种写法:to对象,对象里包含比较多的属性
        <NavLink to={pathname:'/home',search:'',hash:'',key:'123',state:{}} replace>
            <span>首页</span>
        </NavLink>
    
    // Link:主要用于链接
    // 用法与NavLink一致
    
    • Switch
    // 单个路由匹配:如果匹配到一个路由,就结束匹配
        <Switch>
            <Route path="/home" component={Home}/>
            <Route path='/contracts/list/add' component={ContractListDetail}/>
            <Route path='/contracts/list/edit/:id' component={ContractListDetail}/>
        </Switch>
    
    • Redirect
    // 路由重定向
    
    <Redirect to='/login'/>  // 重定向到login
    
    • 嵌套子路由
    // "/home"是"/"下的子路由,需要用render的形式
    
    <Route path='/' render={()=>
        <Admin>
            <Switch>
                <Route path="/home" component={Home}/>
            </Switch>
        </Admin>
    }/>
    
    // Admin组件
    
    export default class Admin extends React.Component{
        render() {
            return (
                <Layout style={{ minHeight: '100vh' }}>
                    <Sidebar/>
                    <Layout>
                        <Header/>
                        <Content style={{ padding: '10px 10px 0'}}>
                            {this.props.children}  // 这里就是各个子路由对应的组件
                        </Content>
                        <Footer/>
                    </Layout>
                </Layout>
            );
        }
    }
    

    相关文章

      网友评论

          本文标题:Redux状态管理与React-router

          本文链接:https://www.haomeiwen.com/subject/roidpqtx.html