dva开发cnode网站(7)

注册逻辑完善以及个人中心页面完成
1 reg组件验证逻辑
和login一样的 验证规则
import React , { Component }from ‘react’;
import PropTypes from ‘prop-types’;
import { connect } from ‘dva’;
import { Form, Icon, Input, Button, Checkbox,message} from ‘antd’;
import { routerRedux } from ‘dva/router’;

const backgroundImage = require(‘../assets/back.jpg’);
const FormItem = Form.Item;

class Reg extends Component{

handleSubmit = (e) => {
e.preventDefault();
const {dispatch} = this.props
this.props.form.validateFields((err, values) => {
if (!err) {
const { userName,password,againPwd } = values
if (password === againPwd) {
dispatch({ type: ‘user/reg’, payload: { userName,password } })
} else {
message.warning(‘您两次输入的密码不一致’);
}

}
});
}

render() {
const { getFieldDecorator,getFieldError } = this.props.form
return (
<div style={styles.form}>
<h1>注册</h1>
<Form onSubmit={this.handleSubmit}>
<FormItem>
{getFieldDecorator(‘userName’, {
rules: [{ required: true, message: ‘请输入用户名’ },
{max:20,message: ‘最大长度不能超过20’}],
})(
<Input prefix={<Icon type=”user” style={{ color: ‘rgba(0,0,0,.25)’ }} />} placeholder=”用户名” />
)}
</FormItem>
<FormItem>
{getFieldDecorator(‘password’, {
rules: [{ required: true, message: ‘请输入密码’ },
{pattern:/^(?![^a-zA-Z]+$)(?!\D+$)/,message: ‘密码必须包含数字和字母’},
{min:6,message: ‘最小长度为6位’},
{max:12,message: ‘最大长度12位’},],
})(
<Input prefix={<Icon type=”lock” style={{ color: ‘rgba(0,0,0,.25)’ }} />} type=”password” placeholder=”密码” />
)}
</FormItem>
<FormItem>
{getFieldDecorator(‘againPwd’, {
rules: [{ required: true, message: ‘请输入确认密码’ },
{pattern:/^(?![^a-zA-Z]+$)(?!\D+$)/,message: ‘密码必须包含数字和字母’},
{min:6,message: ‘最小长度为6位’},
{max:12,message: ‘最大长度12位’},],
})(
<Input prefix={<Icon type=”lock” style={{ color: ‘rgba(0,0,0,.25)’ }} />} type=”password” placeholder=”再次输入密码” />
)}
</FormItem>
<FormItem>
<Button block type=”primary” onClick={this.handleSubmit}>
注册
</Button>
<a>忘记密码</a>
或 <a href=”#/login”>登陆!</a>
</FormItem>
</Form>

</div>
)

}
componentWillMount () {
if(this.props.state.user.isLogin) {
this.props.dispatch(routerRedux.push(‘/’))
}
}
}

const styles = {
form: {
maxWidth: ‘400px’,
margin: ‘0 auto’,
paddingTop: ‘100px’,
}
};

Reg.propTypes = {

};

function mapStateToProps(state) {
return {
state
}
}

// export default ListData;
export default connect(mapStateToProps)(Form.create()(Reg));
2 userService加入注册api
有后台的话请换成自己的
export function regUser({ userName,password}) {
return {
userName: `${userName}`,
password: `${password}`
};
}
3 usermodel中加入注册action
应为是注册,所以没有对state中的数据作处理。顺带把退出登陆action也做了
import * as userService from ‘../services/userService’;
import { routerRedux } from ‘dva/router’;

export default {
namespace: ‘user’,
state:{
isLogin:false,
user:{}
},
effects: {
*login({ payload: { userName,password } }, { call, put }) {
const result = yield call(userService.getUser, { userName,password })
yield put({
type: ‘updateUser’,
payload: {
result
}
})
yield put(routerRedux.push(‘/’))
},
*reg({ payload: { userName,password } }, { call, put }) {
const result = yield call(userService.regUser, { userName,password })
yield put(routerRedux.push(‘/login’))
},
*logOut({ payload: {} },{ call, put }){
yield put({type: ‘userOut’})
}
},

reducers: {
‘updateUser'(state, { payload: data }) {
let r = data.result
return {isLogin:true,user:r}
},
‘userOut'(state) {
return {isLogin:false,user:{}}
}
},

};

4 Person组件创建,来展示个人中心的数据
import React , { Component }from ‘react’;
import { Card, Col, Row , Timeline, Icon} from ‘antd’;
import PropTypes from ‘prop-types’;
import { connect } from ‘dva’;
import ‘./my.css’;

class Person extends Component{

render() {
return (
<div style={{ background: ‘#ECECEC’, padding: ’30px’ }}>
<Row gutter={16}>
<Col span={8}>
<Card title=”个人信息” bordered={false}>
<p>性别:{this.props.state.user.user.sex}</p>
<p>工作:{this.props.state.user.user.job}</p>
<p>兴趣:{this.props.state.user.user.like}</p>
<p>公司:{this.props.state.user.user.work}</p>
<p>工作地址:{this.props.state.user.user.location}</p>
<p>博客:{this.props.state.user.user.blog}</p>
<p>简介:{this.props.state.user.user.desp}</p>
</Card>
</Col>
<Col span={8}>
<Card title=”dva课程进度” bordered={false}>
<Timeline>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>1 dva初始化工程,导航菜单</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>2 列表数据渲染</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>3 react-markdown渲染详情页</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>4 数据分类标签</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>5 登陆注册等页面</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>6 登陆逻辑以及路由权限</Timeline.Item>
<Timeline.Item dot={<Icon type=”check-circle-o” style={{ fontSize: ’16px’ }} />} color=”green”>7 注册逻辑</Timeline.Item>
<Timeline.Item dot={<Icon type=”clock-circle-o” style={{ fontSize: ’16px’ }} />} color=”red”>8 课程总结</Timeline.Item>
</Timeline>
</Card>
</Col>
<Col span={8}>
<Card title=”我的帖子” bordered={false}>
<p>1.服务器迁移至 aws 日本机房</p>
<p>2.学好java</p>
<p>3.搞定python</p>
<p>4.上手react</p>
<p>5.人工智能发展</p>
</Card>
</Col>
</Row>
</div>
)
}

componentWillMount () {

}
}

Person.propTypes = {
id: PropTypes.string.isRequired,
};

function mapStateToProps(state) {
return {
state
};
}

// export default ListData;
export default connect(mapStateToProps)(Person);
5 个人中心页面创建MyPage

使用了Person组件

import React from ‘react’;
import { connect } from ‘dva’;
import Header from ‘../components/Header’;
import Person from ‘../components/Person’;

function MyPage() {
return (
<div>
<Header keys={[‘my’]}/>
<div style={{paddingTop:20,paddingLeft:100,paddingRight:100,paddingBottom:50}}>
<Person/>
</div>
</div>
);
}

MyPage.propTypes = {
};

export default connect()(MyPage);
6 个人中心需要加入权限判断
在路有中使用AuthRouter
import React from ‘react’;
import { Router, Route, Switch } from ‘dva/router’;
import IndexPage from ‘./routes/IndexPage’;
import DetailPage from ‘./routes/DetailPage’;
import NewUserPage from ‘./routes/NewUserPage’;
import ApiPage from ‘./routes/ApiPage’;
import AboutPage from ‘./routes/AboutPage’;
import LoginPage from ‘./routes/LoginPage’;
import RegPage from ‘./routes/RegPage’;
import MyPage from ‘./routes/MyPage’;
import AuthRouter from ‘./components/AuthRouter’;

function RouterConfig({ history }) {
return (
<Router history={history}>
<Switch>
<Route path=”/” exact component={IndexPage} />
<Route path=”/detail/:id” exact component={DetailPage} />
<Route path=”/into” exact component={NewUserPage} />
<Route path=’/about’ component={AboutPage}/>
<Route path=”/login” exact component={LoginPage} />
<Route path=”/reg” exact component={RegPage} />
<AuthRouter path=’/api’ component={ApiPage}></AuthRouter>
<AuthRouter path=’/my’ component={MyPage}></AuthRouter>
</Switch>
</Router>
);
}

export default RouterConfig;
7 修改Header组件,动态显示登陆,注册,个人中心,退出登陆

import React from ‘react’;
import { Menu, Icon, Input,Avatar } from ‘antd’;
import PropTypes from ‘prop-types’;
import {Link} from ‘dva/router’;
import { connect } from ‘dva’;

const Search = Input.Search;

const Header = ({dispatch,state,keys}) => {
const isLoged = state.user.isLogin

function MyHeader() {
function logOut(e){
e.preventDefault();
console.log(‘logout’);
dispatch({ type: ‘user/logOut’,payload: {}})
}
if(isLoged){
return <Menu
selectedKeys={keys}
mode=”horizontal”
>
<Menu.Item key=”node” disabled>
<Icon type=”tag” />CNODE
</Menu.Item>
<Menu.Item key=”search”>
<Search placeholder=”input text search”
onSearch={v => console.log(v)}
enterButton/>
</Menu.Item>
<Menu.Item key=”index”>
<Link to=”/”><Icon type=”appstore” />首页</Link>
</Menu.Item>
<Menu.Item key=”into”>
<Link to=”/into”><Icon type=”appstore” />新手入门</Link>
</Menu.Item>
<Menu.Item key=”api”>
<Link to=”/api”><Icon type=”appstore” />API</Link>
</Menu.Item>
<Menu.Item key=”about”>
<Link to=”/about”><Icon type=”appstore” />关于</Link>
</Menu.Item>
<Menu.Item key=”my”>
<Avatar src=”https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png” />
<span style={{fontSize:16}}><Link to=”/my”>{state.user.user.name}</Link></span>
</Menu.Item>
<Menu.Item key=”logout”>
<Icon type=”logout”/><span onClick={logOut}>退出登陆</span>
</Menu.Item>
</Menu>
}else{
return <Menu
selectedKeys={keys}
mode=”horizontal”
>
<Menu.Item key=”node” disabled>
<Icon type=”tag” />CNODE
</Menu.Item>
<Menu.Item key=”search”>
<Search placeholder=”input text search”
onSearch={v => console.log(v)}
enterButton/>
</Menu.Item>
<Menu.Item key=”index”>
<Link to=”/”><Icon type=”appstore” />首页</Link>
</Menu.Item>
<Menu.Item key=”into”>
<Link to=”/into”><Icon type=”appstore” />新手入门</Link>
</Menu.Item>
<Menu.Item key=”api”>
<Link to=”/api”><Icon type=”appstore” />API</Link>
</Menu.Item>
<Menu.Item key=”about”>
<Link to=”/about”><Icon type=”appstore” />关于</Link>
</Menu.Item>
<Menu.Item key=”reg”>
<Link to=”/reg”><Icon type=”appstore” />注册</Link>
</Menu.Item>
<Menu.Item key=”login”>
<Link to=”/login”><Icon type=”appstore” />登陆</Link>
</Menu.Item>
</Menu>
}
}
return (
<MyHeader/>
)

}

Header.propTypes = {
keys: PropTypes.array.isRequired
};
function mapStateToProps(state) {
return {
state
}
}

// export default ListData;
export default connect(mapStateToProps)(Header);
好不容易坚持更完了dva的实战入门课程。cnode的整个功能都已经实现,原网站是使用得github的授权登陆。本课程中是模拟了后台api来登陆注册,虽然是假数据,但是足够你明白前后的交互。下节课总结一下,为本次课程画上句号,希望对学习react的你有一定的帮助。
今天的课程就到这里了,别忘了关注我 mike啥都想搞

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理