-
Notifications
You must be signed in to change notification settings - Fork 36
Open
Description
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
Labels
No labels
