Skip to content

关于登录部分redux的集成 #2

@dL-hx

Description

@dL-hx

15.2 登录部分封装redux

在登录页面点击登录, 将[用户名] 信息显示在页面中

[TOC]

实现思路:

  • 找到[用户名]这个信息保存在那个变量中(params.username)
  • 通过redux 将其存入全局的state 中
  • 通过redux 数据流,将数据替换原本的state.userName

一 定义事件行为

定义切换用户名action:switchUsers()

1. action代码

// src\redux\action\index.js
/*
* Action类型:用户事件操作 
*/

export const type = {
    SWITCH_MENU:'SWITCH_MENU',
    SWITCH_USERS:'SWITCH_USERS'
}

//菜单点击切换,修改面包屑名称
export function switchMenu(menuName) {
    return {
        type:type.SWITCH_MENU,
        menuName
    }
}

// 用户点击登录,切换用户名称
export function switchUsers(userName) {
    return {
        type:type.SWITCH_USERS,
        userName
    }
}

二 定义reducer数据处理

定义reducer,处理action 的事件,将数据存入state中

2.reducer代码

// src\redux\reducer\index.js
/*
 * Reducer: 数据处理
 */

import { type } from "./../action";
const initialState = {
  menuName: "首页"
};

const ebikeData = (state = initialState, action) => {
  switch (action.type) {
    case type.SWITCH_MENU:
      return {
        ...state, // 旧值
        menuName: action.menuName // 新值
      };
    case type.SWITCH_USERS:
      return {
        ...state, // 旧值
        userName: action.userName //新值
      };
    default:
      return {
        ...state
      };
  }
};

export default ebikeData;

三 引入redux连接器,导入事件行为

3.1 建立redux连接

// src\pages\login\index.js

import { connect } from "react-redux"; // 连接器

import { switchUsers } from "./../../redux/action"; //事件行为

class Login extends React.Component {

​ ...

}

export default connect()(Login);

3.2派发dispatch

事件派发,自动调用reducer,通过reducer讲用户名保存到store对象中

 loginReq = params => {
    // 事件派发,自动调用reducer,通过reducer讲用户名保存到store对象中
    const { dispatch } = this.props;
    dispatch(switchUsers(params.username));
    window.location.href = "/#/";
  };

3. login代码

// src\pages\login\index.js
import React from "react";
import { Form, Input, Button, Modal } from "antd";
import Footer from "../../components/Footer";
import "./index.less";
import { connect } from "react-redux"; // 连接器
import { switchUsers } from "./../../redux/action"; //事件行为
const FormItem = Form.Item;

class Login extends React.Component {
  state = {};

  componentDidMount() {
    //每次进入登录页清除之前的登录信息
  }

  loginReq = params => {
    // 事件派发,自动调用reducer,通过reducer讲用户名保存到store对象中
    const { dispatch } = this.props;
    dispatch(switchUsers(params.username));
    window.location.href = "/#/";
  };

  render() {
    return (
      <div className="login-page">
        <div className="login-header">
          <div className="logo">
            <img src="/assets/logo-ant.svg" alt="慕课后台管理系统" />
            React全家桶+AntD 共享经济热门项目后台管理系统
          </div>
        </div>
        <div className="login-content-wrap">
          <div className="login-content">
            <div className="word">
              共享出行 <br />
              引领城市新经济
            </div>
            <div className="login-box">
              <div className="error-msg-wrap">
                <div className={this.state.errorMsg ? "show" : ""}>
                  {this.state.errorMsg}
                </div>
              </div>
              <div className="title">慕课欢迎你</div>
              <LoginForm ref="login" loginSubmit={this.loginReq} />
            </div>
          </div>
        </div>
        <Footer />
      </div>
    );
  }
}
export default connect()(Login);

class LoginForm extends React.Component {
  state = {};

  loginSubmit = e => {
    e && e.preventDefault();
    const _this = this;
    this.props.form.validateFieldsAndScroll((err, values) => {
      if (!err) {
        var formValue = _this.props.form.getFieldsValue();
        _this.props.loginSubmit({
          username: formValue.username,
          password: formValue.password
        });
      }
    });
  };

  checkUsername = (rule, value, callback) => {
    var reg = /^\w+$/;
    if (!value) {
      callback("请输入用户名!");
    } else if (!reg.test(value)) {
      callback("用户名只允许输入英文字母");
    } else {
      callback();
    }
  };

  checkPassword = (rule, value, callback) => {
    if (!value) {
      callback("请输入密码!");
    } else {
      callback();
    }
  };

  render() {
    const { getFieldDecorator } = this.props.form;
    return (
      <Form className="login-form">
        <FormItem>
          {getFieldDecorator("username", {
            initialValue: "admin",
            rules: [{ validator: this.checkUsername }]
          })(<Input placeholder="用户名" />)}
        </FormItem>
        <FormItem>
          {getFieldDecorator("password", {
            initialValue: "admin",
            rules: [{ validator: this.checkPassword }]
          })(
            <Input
              type="password"
              placeholder="密码"
              wrappedcomponentref={inst => (this.pwd = inst)}
            />
          )}
        </FormItem>
        <FormItem>
          <Button
            type="primary"
            onClick={this.loginSubmit}
            className="login-form-button"
          >
            登录
          </Button>
        </FormItem>
      </Form>
    );
  }
}
LoginForm = Form.create({})(LoginForm);

至此,数据已经存入state中

四 引用state中的数据

引用state中的数据,修改原有的用户名中的固定的值,为:this.props.userName

mapStateToProps will be invoked to determine how to map the new state to the props for Header

将调用mapStateToProps来确定如何将新状态映射到Header的props

// src/components/Header/index.js
	...
//将state.menuName 绑定到 props 的menuName,userName
const mapStateToProps = state => {
    console.log(state)
    return {
        menuName: state.menuName,
        userName:state.userName
    }
};

继而,通过this.props.属性 ,去使用该属性

<Col span={menuType?18:24}>
 +   <span>欢迎, {this.props.userName||this.state.userName} </span>
    <a onClick={this.showExitConfirm}>退出</a>
</Col>

如果存在从登录页面传递过来的userName的值,则使用前者,否则默认使用原本设置的userName,

即(this.state.userName='太阳王子')

{this.props.userName||this.state.userName} 

4. Header代码

// src/components/Header/index.js
import React from 'react';
/*
Header组件 分两部分建立两行Row
第一行是用户的个人信息(这里以后要通过变量传输进来)
* */
import {Row, Col,Modal} from "antd";
import './index.less'
import Util from '../../utils/utils'//导入公共机制
import axios from "../../axios";//引入axios组件
import {connect} from 'react-redux'  //连接器

class Header extends React.Component {
    //声明 state变量 在setState之前要声明变量
    state = {};

    componentWillMount() {        
        this.setState({
            userName: '太阳王子',
        });
        /*
        创建定时器,每隔一秒获取时间
        * 获取时间的方法
        */
        setInterval(() => {
            // new Date();
            let sysTime = Util.formateDate(new Date().getTime());
            this.setState({
                sysTime
            })
        }, 1000);
        this.getWeatherAPIData();//在这里调用下天气
    }

    /*定义得到API天气的方法*/
    getWeatherAPIData() {
        //通过jsonp的方式  调用百度Api接口
        //1.安装jsonp插件             yarn add jsonp --save
        //2.对jsonp插件进行的封装   新建文件夹axios-----index.js
        //3.通过axios插件来发送jsonp()方法
        //通过字符串的方式发送url
        //地区动态储存,定义变量   city            // url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
        //对中文进行编码,转为页面字符
        // 编码后通过   .then  进行接收

        let city = '咸阳';

        axios.jsonp({
            // url:'http://api.map.baidu.com/telematics/v3/weather?location='+this.city+'&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
            url: 'http://api.map.baidu.com/telematics/v3/weather?location=' + encodeURIComponent(city) + '&output=json&ak=3p49MVra6urFRGOT9s8UBWr2'
        }).then((res) => {//通过这里拿到返回值,可以先看下返回值是什么

            if (res.status == 'success') {//状态成功取得数据进行使用
                let data = res.results[0].weather_data[0];
                this.setState({//将状态设置进去
                    date:data.date,
                    dayPictureUrl: data.dayPictureUrl,
                    weather: data.weather
                })
            }
        })
    }

    showExitConfirm=()=> {
        Modal.confirm({
            title:'是否确定退出系统?',
            onOk(){
                window.location.href = '/#/login';
            },
            onCancel(){
                console.log('Cancel');
            }
        })
    }
    render() {
        // 取出menuType 用作二级导航(父组件Common.js传来)
        const menuType = this.props.menuType;
        return (
            <div className="header">
                <Row className="header-top">
                    {
                      menuType?
                        <Col span="6" className="logo">
                          <img src="/assets/logo-ant.svg" alt=""/>
                          <span>IMooc 通用管理系统</span>
                        </Col>:''
                    }
                    <Col span={menuType?18:24}>
                        <span>欢迎, {this.props.userName||this.state.userName} </span>
                        <a onClick={this.showExitConfirm}>退出</a>
                    </Col>
                </Row>
                {
                    menuType?'':<Row className="breadcrumb">
                        <Col span="4" className="breadcrumb-title">
                            {/* 首页 */}
                            {this.props.menuName}
                        </Col>
                        <Col span="20" className="weather">
                            <span className="date">{this.state.sysTime}</span>
                            <span className="weather-img">
                            <img src={this.state.dayPictureUrl} alt=""/>
                        </span>
                            <span className="weather-detail">
                            {this.state.weather}
                                {/*{this.state.date}*/}
                        </span>
                        </Col>
                    </Row>
                }
            </div>
        );
    }
}
//将state.menuName 绑定到 props 的menuName
const mapStateToProps = state => {
    console.log(state)
    return {
        menuName: state.menuName,
        userName:state.userName
    }
};
export default connect(mapStateToProps)(Header) 

总结

定义完redux继承之后, 以后的代码只需仿照之前的代码即可仿写,

关键是redux的搭建比较繁琐,可结合14章 redux 集成,进行复习

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions