一 开发环境设置
1 安装包环境
项目包如下
链接:https://pan.baidu.com/s/1C-ZY9rWU-8ZugE4EwVveWw
提取码:744p
相关react介绍链接如下
https://blog.51cto.com/11233559/2443713解压并修改目录为blog 没有特殊说明,js 文件均放置在src目录中
2 修改相关信息
1 修改项目信息
2 修改反代和本地监听端口
本环境后端服务ip地址为192.168.1.200,后端python监听端口为80.
3 安装软件
npm i
启动并查看
npm start
二 登录模块功能开发
1 前端路由配置
本次使用react-router 进行路由配置工作
基础例子
https://reacttraining.com/react-router/web/example/basic
官方文档
https://reacttraining.com/react-router/web/guides/quick-start
根据官方示例,修改src/index.js如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About=() => {
return (
<div>
<h2>About</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</div>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
显示结果如下
Route 负责静态路由
path 是匹配的路径,没有path总是匹配。
component 是目标组件。
exact: 布尔值,true 时要求路径完全匹配。
strict: 布尔值,true 时要求严格匹配,但是url字符串可以是自己的字串。地址变化,Router组件会匹配路径,然后使用匹配的组件进行渲染
2 登录前端view层实现
1 全局CSS 配置
添加css目录,并创建全局CSS文件login.css
body {
background: #456;
font-family: SimSun;
font-size: 14px;
}
.login-page{
width: 360px;
padding: 8% 0 0;
margin: auto;
}
.form {
font-family: "Microsoft YaHei",SimSun;
position: relative;
z-index:1;
background: #ffffff;
max-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0,0,0,0.2), 0 5px 5px 0 rgba(0,0,0,0.24);
}
.form input{
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
}
.form button{
text-transform: uppercase;
outline: 0;
background: #4cAf50;
width: 100%;
border: 0;
padding: 15px;
color: #ffffff;
font-size: 14px;
cursor: pointer;
}
.form button:hover,.from button.active,.form button.focus {
background: #43a047;
}
.from .message{
margin: 15px 0 0;
color: #bb33bb;
font-size: 12px;
}
.form .message a{
color: #4caf50;
text-decoration: none;
}
如下
2登录模块view层实现
在component 目录下构建react组件
登录模板
https://codepen.io/colorlib/pen/rxddKy?q=login&limit=all&type=type-pens
添加component目录,其在src下
HTML版登录模板如下
<div class="login-page">
<div class="form">
<form class="register-form">
<input type="text" placeholder="name"/>
<input type="password" placeholder="password"/>
<input type="text" placeholder="email address"/>
<button>create</button>
<p class="message">Already registered? <a href="#">Sign In</a></p>
</form>
<form class="login-form">
<input type="text" placeholder="username"/>
<input type="password" placeholder="password"/>
<button>login</button>
<p class="message">Not registered? <a href="#">Create an account</a></p>
</form>
</div>
</div>
使用此HTML模板来进行构建组件
注意:
搬到React组件中的时候,要将class 属性修改为ClassName
所有标签,必须闭合
login.js 创建
在 component 目录下创建login.js登录组件
使用上面的HTML模板中的登录部分,挪到render函数中。
如下
import React from ‘react‘;
import {Link} from ‘react-router-dom‘;
export default class Login extends React.Component{
render(){
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<button>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
index.js 中添加路由如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘ //引入对象
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About=() => {
return (
<div>
<h2>About</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/login" component={Login} /> {/*此处主要是跳转至login对象*/}
</div>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
导入样式表如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link} from ‘react-router-dom‘;
export default class Login extends React.Component{
render(){
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<button onClick={event =>console.log(event)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
结果如下
页面中默认传递的数据是from data
3 获取触发数据
在src/component/login.js中定义handlerClick函数用于获取触发事件生成的数据
上述的每一次填写会导致页面的刷新,而不是等到点击提交后才刷新,要阻止页面刷新,其实就是要阻止提交,可使用event.preventDefault()来阻止页面的自动提交如何拿到邮箱和密码
event.target.from 返回按钮所在的表单,可看做一个数组
fm[0].value和fm[1].value就是文本框的值
在login组件中使用UserServie实例的方法:
1 在Login构造器中直接进行初始化
2 在props中传入
相关代码如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link} from ‘react-router-dom‘;
export default class Login extends React.Component{
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
console.log(‘邮箱‘,event.target.form[0].value) // 此处用于获取相关用户登录信息,
console.log(‘密码‘,event.target.form[1].value)
}
render(){
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
结果如下
通过上述的event.target.form[1].value可获取到表单提交的数据
3 注册界面view 实现
1 基本页面实现
在component中创建reg.js用于注册函数
import React from ‘react‘;
import ‘../css/login.css‘
import {Link} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
const service= new UserService();
export default class Reg extends React.Component{
render(){
return <_Reg server={service} />; {/*通过此处将service传递下去,后期可以通过props.service.xxx方法来完成数据的注入操作*/}
}
}
class?_Reg???extends??React.Component??{
????handleClick(event)?{
????????event.preventDefault();??//处理页面刷新问题,阻止缺省行为?
????????let?fm=event.target.form;
????????console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //获取注册信息
????}
????render()?{
????????console.log(‘++++++++++++++++++++++++‘)
??????return??(
????????<div?className="login-page">
????????????<div??className="form">
????????????????<form??className="register-form">
????????????????????<input?type="text"?placeholder="姓名"?/>
????????????????????<input?type="text"?placeholder="邮箱"?/>
????????????????????<input?type="password"?placeholder="密码"?/>
????????????????????<input?type="password"?placeholder="确认密码"?/>
????????????????????<button?onClick={this.handleClick.bind(this)}>注册</button>
????????????????????<p?className="message">如果已注册?<Link??to="login">请登陆</Link></p> {/*此处用于跳转*/}
????????????????</form>
????????????</div>
????????</div>???????
???????)
????}??
??}
添加路由
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About=() => {
return (
<div>
<h2>About</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/login" component={Login} />
<Route path="/reg" component={Reg} />
</div>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
上述在表单中填写的内容可在fm[x].value 中直接获取
4 导航栏组件
在index.js中添加导航栏,可方便页面之间的切换
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About=() => {
return (
<div>
<h2>About</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<div>
<ul> {/*导航栏相关*/}
??????????<li><Link?to="/">主页</Link></li>
??????????<li><Link?to="/about">关于</Link></li>
??????????<li><Link?to="/reg">注册</Link></li>
??????????<li><Link?to="/login">登录</Link></li>
????????</ul>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/login" component={Login} />
<Route path="/reg" component={Reg} />
</div>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
5 同步和异步
1 同步
模拟sleep
d1=new Date();
for (var d=new Date();(new Date())-d <1000;);// 此处相当于sleep处理
console.log(‘------------‘)
d2=new Date();
console.log(d2-d1)
结果如下
登录代码相关修改
component/login.js
import React from ‘react‘;
import ‘../css/login.css‘
import {Link} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
export default class Login extends React.Component{
constructor(prpos){
super(prpos);
this.service=new UserService;
this.state={‘ret‘:-1};
}
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
// console.log(‘邮箱‘,event.target.form[0].value) // 此处用于获取相关用户登录信息,
// console.log(‘密码‘,event.target.form[1].value)
console.log(‘this----------‘,this) //此处的this指的是Login 实例,可将此值传入进去用于修改ret 的值来触发页面刷新
let fm=event.target.form
this.service.login(fm[0].value,fm[1].value,this); //此处用于传输当前login及相关表单数据至后端service层
console.log(this.state.ret)
}
render(){
if (this.state.ret != -1 ){ // 此处若发生变化,则会导致其状态刷新
console.log(‘ret‘,this.state.ret) //打印刷新结果
}
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱" defaultValue="[email protected]"/>
<input type="password" placeholder="密码" defaultValue="demo"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
相关代码如下
import axios from ‘axios‘
export default class UserSerive{
login(email,password,obj){
for (var d=new Date();(new Date())-d <10000;);// 此处相当于sleep处理
console.log(‘12433645645765‘)
console.log(email,password,obj)
}
}
结果导致浏览器端在进行数据请求时直接停顿,导致其他相关页面也不能刷新或者点开
2 异步
1 setTimeout
export default class UserSerive{
login(email,password,obj){
setTimeout(()=> {console.log(‘timeout---------‘);obj.setState({‘ret‘:parseInt(Math.random()*100)})},
10*1000
)
console.log(email,password,‘Userservice‘)
}
}
此处的结果是其email,password和‘Userservice‘立即打印,但timeout及后面的打印滞后10s,但在这10s过程中,其页面是可以进行点击的,及其未阻塞当前业务执行。
obj.setState({‘ret‘:parseInt(Math.random()*100)}) 此处用于生成随机整数
2 Promise
官网代码如下
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
class Root {
login(){
new Promise((resolve,reject) => {
setTimeout(
()=> {
console.log(‘timeout......‘)
// reject(‘ok‘);
resolve(‘not ok‘)
},5*1000
)
}
).then( value => {
console.log(‘then++++++++++++++++++++++++++‘)
console.log(‘then-------------------‘,‘UserService‘)
}).catch(value => {
console.log(‘then-------------------------‘)
})
console.log(‘12423423523534564‘)
}
}
login=new Root();
login.login()
结果如下
export default class UserSerive{
login(email,password,obj){
new Promise((resolve,reject) => setTimeout(
() => {
console.log(‘timeout ........‘);
resolve(‘ok‘) //调用此处,将执行then中的代码
},5*1000)).then(value =>
obj.setState({‘ret‘:parseInt(Math.random()*100)}),
console.log(‘then-------------‘)
)
console.log(email,password,‘Userobject‘)
}
}
此处的结果是先打印email,password和‘Userobject‘,5秒之后才进行相关的timeout输出和对应的渲染操作,此处由于页面为改变,因此其不会进行DOM渲染。
测试代码如下
class Root {
login(){
new Promise((resolve,reject) => {
setTimeout(
()=> {
console.log(‘timeout......‘)
reject(‘ok‘);
// resolve(‘not ok‘)
},5*1000
)
}
).then( value => {
console.log(‘then++++++++++++++++++++++++++‘)
console.log(‘then-------------------‘,‘UserService‘)
}).catch(value => {
console.log(‘then-------------------------‘)
})
console.log(‘12423423523534564‘)
}
}
login=new Root();
login.login()
结果如下,此处打印的结果是直接输出为12423423523534564,之后在timeout超时后输出then中的内容,此处表明上述的timeout并未阻塞程序本身的运行,此处便是异步调用方式。其不会影响当前请求的下一个数据处理
3 axios
axios 是一个基于promise的HTTP异步库,可以用在浏览器或nodejs中。
使用axios发起异步调用,完成POST,GET 方法的数据提交,可参照官网例子
http://www.axios-js.com/zh-cn/docs/
安装
npm i axios
导入
import axios from ‘axios‘
基本实例如下
基本GET 实现
axios.get(‘/user‘, { //此处的user是api的url,指定的是绝对路径
params: { //此处表示的是传递的值
ID: 12345
}
})
.then(function (response) { //此处表示请求成功的返回值
console.log(response);
})
.catch(function (error) { //此处表示失败的返回值
console.log(error);
});
基本POST实现
axios.post(‘/user‘, {
firstName: ‘Fred‘,
lastName: ‘Flintstone‘
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
6 登录接口实现
具体代码如下
import?{?comparer?}?from?"mobx";
import??axios??from??‘axios‘
//?import?{?object?}?from?"prop-types";
//?import?{?resolve?}?from?"dns";
//用户逻辑的处理?
export?default??class??UserService{
????login(email,password,obj)?{
????????axios.post(‘/api/user/login‘,?{
????????????‘email‘:??email,
????????????‘password‘:?password
??????????})
??????????.then(function?(response)?{???//成功执行的操作
????????????console.log(response,‘===================‘);
????????????console.log(response.data)
????????????console.log(response.status);
obj.setState({‘ret‘:parseInt(Math.random()*100)}) //当返回成功时进行改变状态,进入渲染dom
??????????})
??????????.catch(function?(error)?{?//失败执行的操作
????????????console.log(error);
??????????});
????????console.log(email,password,‘UserService‘)//?如何传输,传输什么,返回什么,如何返回的问题
????????}
}
前端页面实现如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
export default class Login extends React.Component{
constructor(prpos){
super(prpos);
this.service=new UserService;
this.state={‘ret‘:-1};
}
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
// console.log(‘邮箱‘,event.target.form[0].value) // 此处用于获取相关用户登录信息,
// console.log(‘密码‘,event.target.form[1].value)
console.log(‘this----------‘,this) //此处的this指的是Login 实例,可将此值传入进去用于修改ret 的值来触发页面刷新
let fm=event.target.form
this.service.login(fm[0].value,fm[1].value,this);
}
render(){
if (this.state.ret !=-1 ) //此处用于判断当不为-1时直接跳转到about页面即可
return <Redirect to=‘/about‘ />
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱" defaultValue="[email protected]"/>
<input type="password" placeholder="密码" defaultValue="demo"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
上述中的defaultValue 是为了方便登录而处理的。
获取数据如下
7 localStorage及过期实现
使用store进行写入客户端的localstorage中,并使用其自带的插件来进行处理过期机制
相关官网
https://github.com/marcuswestin/store.js/
过期插件
相关过期代码如下
https://github.com/marcuswestin/store.js/blob/master/plugins/expire_test.js
添加过期插件和配置
store.addPlugin(require(‘store/plugins/expire‘))
配置过期
store.set(‘token‘,response.data.token,(new Date()).getTime()+(8*3600*1000));
8 Mobx 状态管理
1 需求
一个组件的onClick 触发事件响应函数,此函数会调用后台服务,但是后台服务比较耗时,等处理完成,需要引起组件的渲染操作。
要组件渲染,则需要改变组件的props或state
1 同步调用
将index.js进行暂时的修改如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
class Service{
handler(e){
console.log(‘pending..............‘)
for (let d=new Date();new Date() -d < 1000*e;) //此处是同步阻塞模型
console.log(‘输出‘)
return parseInt(Math.random()*100)
}
}
class Root extends React.Component{
state={‘ret‘:-100}
handlerClink(){
this.setState({‘ret‘:this.props.service.handler(10)})
}
render(){
return (<div>
<button onClick={this.handlerClink.bind(this)}> 点击触发按钮 </button>
<span style={{color:‘red‘}}> {new Date().getTime()} {this.state.ret} </span>
</div>)
}
}
ReactDom.render(<Root service={ new Service() }/>,document.getElementById(‘root‘));
结果是过了10秒页面进行刷新,但其在此期间不能点击其他页面
2 异步调用
思路一,使用setTimeout
使用setTimeout,有两个问题1 无法向内部的待执行函数传递参数,比如Root实例
2 延时执行的函数返回值复发获取,所以无法通知Root
思路二 promise 异步执行
promise异步执行,若执行成功,则调用回调
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class Service{
handler(obj){
new Promise((resolve,reject)=>{
setTimeout(()=> //此处成功,则返回为此值
resolve(‘ok‘)
,5000)
}).then(value => {
obj.setState({‘ret‘:parseInt(Math.random()*1000)})
})
}
}
class Root extends React.Component{
state={‘ret‘:-100}
handlerClink(){
console.log(‘触发‘)
this.props.service.handler(this)
}
render(){
return (<div>
<button onClick={this.handlerClink.bind(this)}> 点击触发按钮 </button>
<span style={{color:‘red‘}}> {new Date().getTime()} {this.state.ret} </span>
</div>)
}
}
ReactDom.render(<Root service={ new Service() }/>,document.getElementById(‘root‘));
结果如下
上述方式在事件被调用的过程中,其没有影响到页面的点击,不会阻塞页面的正常处理。
3 Mobx 实现
observable装饰器: 设置被观察者
observer 装饰器:设置观察者
1 Mobx + promise 实现代码
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import {observable} from ‘mobx‘
import {observer} from ‘mobx-react‘
class Service{
@observable ret=-100;
handler(){
new Promise((resolve,reject) => {
setTimeout(()=>resolve(‘ok‘),5000)
}).then((value)=> {
this.ret=parseInt(Math.random()*100)
})
}
}
@observer
class Root extends React.Component{
handlerClink(){
this.props.service.handler();
}
render(){
return <div>
<button onClick={this.handlerClink.bind(this)}> 点击触发 </button>
<span style={{color:‘red‘}} > {new Date().getTime()} {this.props.service.ret} </span>
</div>
}
}
ReactDom.render(<Root service={new Service() } />,document.getElementById(‘root‘));
其基本结论和上面的相同,其点击不会导致页面问题,实现了异步请求的目的
2 mobx+axiso 代码实现
login登录触发到about页面如下
src/service/user.js中代码修改如下
import??axios??from??‘axios‘
import??{observable}??from??‘mobx‘
import??store??from??‘store‘
store.addPlugin(require(‘store/plugins/expire‘))??//加载过期插件,此处返回一个对象
//用户逻辑的处理?
export?default??class??UserService{
[email protected]?loggin=0;??//?被观察对象,已经被观察了,一旦值发生变化,则观察者就知道了
?? login(email,password)?{
????????axios.post(‘/api/user/login‘,?{
????????????‘email‘:??email,
????????????‘password‘:?password
??????????})
??????????.then(?(response)?=>?{???//成功执行的操作??this的问题通过箭头函数解决?
????????????console.log(response,‘===================‘);
????????????console.log(response.data)
????????????console.log(response.status);
????????????//?obj.setState({ret:1000})??//state触发导致改变
????????????store.set(‘token‘,response.data.token,(new?Date()).getTime()+(8*3600*1000));//getTime拿到的是时间,但其是毫秒
????????????this.loggin?=?Math.random()?*?100;??//?修改值
console.log(this.loggin)
??????????})
??????????.catch(?(error)?=>?{?//失败执行的操作
????????????console.log(error);
??????????});
????????//for??(var?d=new?Date();(new?Date())-d?<?10*1000;);?//?此处是同步处理?
????????console.log(email,password,‘UserService‘)//?如何传输,传输什么,返回什么,如何返回的问题
????????}
}
src/component/login.js 结果如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
let service = new UserService()
export default class Login extends React.Component {
render(){
return < _Login service={service}/>
}
}
@observer
class _Login extends React.Component{
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
console.log(‘this----------‘,this) //此处的this指的是Login 实例,可将此值传入进去用于修改ret 的值来触发页面刷新
let fm=event.target.form
this.props.service.login(fm[0].value,fm[1].value,this);
}
render(){
if ( this.props.service.loggin)
return <Redirect to=‘/about‘ />
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱" defaultValue="[email protected]"/>
<input type="password" placeholder="密码" defaultValue="demo"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
整体结果如下
9 注册接口完善
1 参数解构
let a=1,b=2,c=3
var obj={a,b,c}
console.log(obj)
结果如下
2 注册接口完善
src/service/user.js中配置如下
import??axios??from??‘axios‘
import??{observable}??from??‘mobx‘
import??store??from??‘store‘
store.addPlugin(require(‘store/plugins/expire‘))??//加载过期插件,此处返回一个对象
//用户逻辑的处理?
export?default??class??UserService{
?? @observable?loggin=0;??//?被观察对象,已经被观察了,一旦值发生变化,则观察者就知道了
@observable regin=0; //定义登录的被观察对象
?? login(email,password)?{
????????axios.post(‘/api/user/login‘,?{
????????????‘email‘:??email,
????????????‘password‘:?password
??????????})
??????????.then(?(response)?=>?{???//成功执行的操作??this的问题通过箭头函数解决?
????????????console.log(response,‘===================‘);
????????????console.log(response.data)
????????????console.log(response.status);
????????????//?obj.setState({ret:1000})??//state触发导致改变
????????????store.set(‘token‘,response.data.token,(new?Date()).getTime()+(8*3600*1000));//getTime拿到的是时间,但其是毫秒
????????????this.loggin?=?Math.random()?*?100;??//?修改值
console.log(this.loggin)
??????????})
??????????.catch(?(error)?=>?{?//失败执行的操作
????????????console.log(error);
??????????});
????????//for??(var?d=new?Date();(new?Date())-d?<?10*1000;);?//?此处是同步处理?
????????console.log(email,password,‘UserService‘)//?如何传输,传输什么,返回什么,如何返回的问题
????????}
reg(name,email,password){
axios.post(‘/api/user/reg‘,{
name,email,password}
).then((response)=> {
console.log(response.data);
this.regin=parseInt(Math.random()*100); //改变触发
store.set(‘token‘,response.data.token,(new?Date()).getTime()+(8*3600*1000));//getTime拿到的是时间,但其是毫秒
}).catch((error)=> {
console.log(error.data);
})
}
}
src/component/reg.js中配置如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
const service= new UserService();
export default class Reg extends React.Component{
render(){
return <_Reg service={service} />; {/*通过此处将service传递下去,后期可以通过props.service.xxx方法来完成数据的注入操作*/}
}
}
@observer
class ?_Reg???extends??React.Component??{
handleClick(event)?{
????????event.preventDefault();??//处理页面刷新问题,阻止缺省行为?
????????let?fm=event.target.form;
????????console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //获取注册信息
this.props.service.reg(fm[0].value,fm[1].value,fm[2].value)
console.log(this.props.service.regin)
????}
????render()?{
if (this.props.service.regin)
return <Redirect to=‘/about‘ />
??????return??(
????????<div?className="login-page">
????????????<div??className="form">
<form className="register-form">
<input type="text" placeholder="用户名"/>
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<input type="password" placeholder="确认密码"/>
<button onClick={this.handleClick.bind(this)}>注册</button> {/*触发按钮*/}
<p className="message">已经注册 <Link to="/reg">请登录</Link></p>
</form>
????????????</div>
????????</div>???????
???????)
????}??
??}
10 增加信息提示
网页开发中,不管操作成功与否,有很多提示信息,目前信息都是从控制台输出的,用户看不到,使用Antd的message组件显示友好的信息提示。
1 临时修改index.js页面获取提示信息
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import { message } from ‘antd‘;
import ‘antd/lib/message/style‘
const info = () =>{
message.info(‘触发构建‘)
}
class Root extends React.Component{
render(){
return (<div>
<button type="prmary" onClick={info}>点击触发</button>
</div>)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import { message } from ‘antd‘;
import ‘antd/lib/message/style‘
const info = () =>{
message.success(‘this is first‘,5) //此处的5为显示延迟为5
}
class Root extends React.Component{
render(){
return (<div>
<button type="prmary" onClick={info}>点击触发</button>
</div>)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
2 同时触发多条数据
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import { message } from ‘antd‘;
import ‘antd/lib/message/style‘
const info = () =>{
message.success(‘this is first‘,5)
message.info(‘this is info‘)
}
class Root extends React.Component{
render(){
return (<div>
<button type="prmary" onClick={info}>点击触发</button>
</div>)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
3 业务添加提示信息
index.js代码还原
代码修改如下
import??axios??from??‘axios‘
import??{observable}??from??‘mobx‘
import??store??from??‘store‘
store.addPlugin(require(‘store/plugins/expire‘))??//加载过期插件,此处返回一个对象
//用户逻辑的处理?
export?default??class??UserService{
?? @observable?loggin=0;??//?被观察对象,已经被观察了,一旦值发生变化,则观察者就知道了
@observable regin=0; //定义登录的被观察对象
@observable loginerrMsg=‘‘; //定义发生登录错误的输出结果
@observable regerrMsg=‘‘; //定义注册发生错误的输出结果
?? login(email,password)?{
????????axios.post(‘/api/user/login‘,?{
????????????‘email‘:??email,
????????????‘password‘:?password
??????????})
??????????.then(?(response)?=>?{???//成功执行的操作??this的问题通过箭头函数解决?
????????????console.log(response,‘===================‘);
????????????console.log(response.data)
????????????console.log(response.status);
????????????//?obj.setState({ret:1000})??//state触发导致改变
????????????store.set(‘token‘,response.data.token,(new?Date()).getTime()+(8*3600*1000));//getTime拿到的是时间,但其是毫秒
????????????this.loggin?=?Math.random()?*?100;??//?修改值
console.log(this.loggin)
??????????})
??????????.catch(?(error)?=>?{?//失败执行的操作
????????????console.log(error);
this.loginerrMsg=true; //当发生错误时触发
??????????});
????????//for??(var?d=new?Date();(new?Date())-d?<?10*1000;);?//?此处是同步处理?
????????console.log(email,password,‘UserService‘)//?如何传输,传输什么,返回什么,如何返回的问题
????????}
reg(name,email,password){
axios.post(‘/api/user/reg‘,{
name,email,password}
).then((response)=> {
console.log(response.data);
this.regin=parseInt(Math.random()*100); //改变触发
store.set(‘token‘,response.data.token,(new?Date()).getTime()+(8*3600*1000));//getTime拿到的是时间,但其是毫秒
}).catch((error)=> {
this.regerrMsg=true; //当发生错误时进行触发
console.log(error.data);
})
}
}
src/component/login.js代码如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
import { message } from ‘antd‘;
let service = new UserService()
export default class Login extends React.Component {
render(){
return < _Login service={service}/>
}
}
@observer
class _Login extends React.Component{
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
console.log(‘this----------‘,this) //此处的this指的是Login 实例,可将此值传入进去用于修改ret 的值来触发页面刷新
let fm=event.target.form
this.props.service.login(fm[0].value,fm[1].value,this);
}
render(){
if ( this.props.service.loggin)
return <Redirect to=‘/about‘ />
if (this.props.service.loginerrMsg)
{
message.error(‘用户名或密码错误‘,3,()=>{
this.props.service.loginerrMsg=‘‘;
})
}
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱" defaultValue="[email protected]"/>
<input type="password" placeholder="密码" defaultValue="demo"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
src/component/reg.js代码如下
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
import { message } from ‘antd‘;
const service= new UserService();
export default class Reg extends React.Component{
render(){
return <_Reg service={service} />; {/*通过此处将service传递下去,后期可以通过props.service.xxx方法来完成数据的注入操作*/}
}
}
@observer
class ?_Reg???extends??React.Component??{
handleClick(event)?{
????????event.preventDefault();??//处理页面刷新问题,阻止缺省行为?
????????let?fm=event.target.form;
????????console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //获取注册信息
this.props.service.reg(fm[0].value,fm[1].value,fm[2].value)
console.log(this.props.service.regin)
????}
????render()?{
if (this.props.service.regin)
return <Redirect to=‘/about‘ />
if (this.props.service.regerrMsg){
message.error(‘注册失败,请检查相关参数是否正确‘,3,()=>this.props.service.regerrMsg=‘‘)
}
??????return??(
????????<div?className="login-page">
????????????<div??className="form">
<form className="register-form">
<input type="text" placeholder="用户名"/>
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<input type="password" placeholder="确认密码"/>
<button onClick={this.handleClick.bind(this)}>注册</button> {/*触发按钮*/}
<p className="message">已经注册 <Link to="/reg">请登录</Link></p>
</form>
????????????</div>
????????</div>???????
???????)
????}??
??}
结果如下
三 博文模块功能开发
1 接口规则相关
/post/put POST 提交博文的title,content,成功返回JSON的post_id
/post/id GET 返回博文详情。返回JSON的post_id,title,author,author_id,postdate(时间戳),conent 内容
/post/GET 返回博文列表
2 上传博文相关配置
1 相关文档
https://ant.design/components/layout-cn/
2 前端路由配置
index.js中代码如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import Pub from ‘./component/pub‘
import ‘antd/lib/menu/style‘
import ‘antd/lib/icon/style‘
import ‘antd/lib/layout/style‘
import?{?Menu,?Icon,?Layout,Item}?from?‘antd‘
const { Header, Content, Footer } = Layout;
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
const About=() => {
return (
<div>
<h2>About</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<div>
<ul>
??????????<li><Link?to="/">主页</Link></li>
??????????<li><Link?to="/about">关于</Link></li>
??????????<li><Link?to="/reg">注册</Link></li>
??????????<li><Link?to="/login">登录</Link></li>
??????????<li><Link?to="/pub">博客上传</Link></li>
????????</ul>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/login" component={Login} />
<Route path="/reg" component={Reg} />
<Route path="/pub" component={Pub} />
</div>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
3 后端服务配置
service/post.js
import??axios??from??‘axios‘
import??{observable}??from??‘mobx‘
import store from ‘store‘
export default class PostService {
constructor(){
this.instance=axios.create({
baseURL:‘/api/post‘,
});
}
@observable msg="";
pub(title,content) {
console.log(title,content)
this.instance.post(‘/pub‘,{
title,content
},{
headers:{‘jwt‘:store.get(‘token‘)}
}).then((response) => {
console.log(response.data),
console.log(Response.status);
this.msg="博文提交成功"; // 触发事件
}).catch((error)=> {
console.log(error.data);
this.msg="博文提交失败";
})
}
}
4 渲染页面配置
From 表单组件,layout是垂直,onsubmit提交,注意这个提交的this是表单自己
FromItem 表单向,label设置控件的标题,labelCol设置label的宽度,wrapperCol是label后占的宽度,这些都是栅格系统的宽度
INput 输入框,placeholder 提示字符
TextArea文本框,rows 行数
Button按钮。htmlType使用HTML中的type值。submit是提交按钮会触发提交行为,但是handleSubmit中要阻止此行为。
/src/component/pub.js
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/post‘
import {observer} from ‘mobx-react‘
import { Input,message,Button,Form } from ‘antd‘;
import PostService from ‘../service/post‘
const {TextArea} = Input;
import??‘antd/lib/message/style‘
import??‘antd/lib/form/style‘
import??‘antd/lib/input/style‘
import??‘antd/lib/button/style‘
export default class Pub extends React.Component{
render(){
return <_Pub service={new PostService()} />
}
}
@observer
class _Pub extends React.Component{
handleSubmit(event){
event.preventDefault();
console.log(‘pub......‘)
let fm=event.target;
console.log(fm[0].value,fm[1].value)
this.props.service.pub(fm[0].value,fm[1].value)
}
render(){
if (this.props.service.failsg) {
message.error(this.props.service.msg,5,()=> this.props.service.msg=‘‘)
}
if (this.props.service.semsg) {
message.success(this.props.service.semsg,5,()=> this.props.service.semsg=‘‘)
}
????????return??(
????????????<Form?onSubmit={this.handleSubmit.bind(this)}?>
????????????????<Form.Item?label="标题"?wrapperCol={{span:20}}?labelCol={{span:2}}>
????????????<Input?/>
????????????</Form.Item>
????????????????<Form.Item?label="内容"??wrapperCol={{span:20}}?labelCol={{span:2}}>
????????????<TextArea??rows={28}/>
????????????</Form.Item>
????????????<Form.Item???wrapperCol={{span:4,offset:10}}>
????????????????<Button?type="primary"?htmlType="submit"??>发布</Button>
????????????</Form.Item>
????????</Form>
????????);
????}?
}
5 结果如下
3 查看博文列表相关配置及getall
1 相关文档
此处显示需要用到ist,相关链接如下
https://ant.design/components/list-cn/
https://ant.design/components/form-cn/
https://ant.design/components/input-cn/
2 测试页面数据获取
配置渲染页面
在component 中创建Getall.js文件,内容如下
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import ‘antd/lib/message/style‘;
import ‘antd/lib/form/style‘;
import ‘antd/lib/input/style‘;
import ‘antd/lib/button/style‘;
@observer
export default class Getall extends React.Component{
constructor(props){
super(props);
console.log(props);
}
render(){
return <h1>Getall</h1>
}
}
将其加入到index.js中显示结果如下
在输入框中写入http://localhost/list?page=1&size=10 结果如下
由上图可知,其props中包含页面输入框的内容,提取如下
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import ‘antd/lib/message/style‘;
import ‘antd/lib/form/style‘;
import ‘antd/lib/input/style‘;
import ‘antd/lib/button/style‘;
@observer
export default class Getall extends React.Component{
constructor(props){
super(props);
let {location:{search}}=props;
console.log(search) //获取数据
}
render(){
return <h1>Getall</h1>
}
}
结果如下
3 显示层代码实现
/src/component/getall.js 中代码如下
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import { List, Avatar,Pagination } from ‘antd‘;
import ‘antd/lib/list/style‘
import ‘antd/lib/avatar/style‘
import ‘antd/lib/pagination/style‘
@observer
export default class Getall extends React.Component{
constructor(props){
super(props);
let {location:{search}}=props;
this.service=new PostService();
this.service.getall(search);
}
handleChange(page,pageSize){
console.log(page,pageSize)
let search =‘?‘+‘page=‘+page+‘&‘+‘size=‘+pageSize;
console.log(search)
this.service.getall(search)
}
render(){
const data=this.service.posts; //获取数据列表
const pagination=this.service.pagination; //分页功能实现
return (
<div>
<List
itemLayout="horizontal"
dataSource={data}
bordered="true"
split="true"
hideOnSinglePage="true"
renderItem={item => (
<List.Item>
<List.Item.Meta
avatar={<Avatar src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571932022162&di=f108eeab8bc4d45e6d9b85c36581f9ae&imgtype=0&src=http%3A%2F%2Fs7.sinaimg.cn%2Fmw690%2F0065sEcMzy74EYHBPMOa6%26690" />}
title={item.name}
description={item.title}
/>
</List.Item>
)}
/>
<Pagination defaultCurrent={1} total={pagination.count} pageSize={pagination.size} onChange={this.handleChange.bind(this)}/>
</div>
)
}
}
4 逻辑层代码如下
/src/service/post.js
import axios from ‘axios‘
import { observable } from ‘mobx‘
import store from ‘store‘
export default class PostService {
constructor() {
this.instance = axios.create({
baseURL: ‘/api/post‘,
});
}
@observable semsg = "";
@observable failsg = "";
@observable posts = []; //定义输出结果至此容器中
@observable pagination = ‘‘; //定义分页功能相关参数监控
pub(title, content) {
console.log(title, content)
this.instance.post(‘/pub‘, {
title, content
}, {
headers: { ‘jwt‘: store.get(‘token‘) }
}).then((response) => {
console.log(response.data),
console.log(Response.status);
this.semsg = "博文提交成功"; // 触发事件
}).catch((error) => {
console.log(error.data);
this.failsg = "博文提交失败";
})
}
getall(search) {
axios.get(‘/api/post/‘ + search).then(
response => {
console.log(response.data)
this.posts = response.data.posts; //成功的输出结果
this.pagination = response.data.pagination; //携带的相关参数
}
).catch(error=> {
console.log(error.data)
})
}
}
结果如下
4 详情页get配置
1 获取id数据
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import { Card,Row } from ‘antd‘;
export default class Get extends React.Component{
constructor(props){
super(props);
this.service=new PostService();
console.log(props);
}
render(){
return (<div> Get </div>)
}
}
将其加入index.js中结果查看如下
有上述得知,其id获取仍是通过pathname来完成,具体代码如下
2 view层代码如下
/src/component/get.js
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import { Card,Row, message } from ‘antd‘;
import ‘antd/lib/card/style‘
@observer
export default class Get extends React.Component{
constructor(props){
super(props);
this.service=new PostService();
let {location:{pathname}}=this.props;
let [,,id]=pathname.split(‘/‘) // 获取ID
this.service.get(id) //异步传值到后端
}
render(){
let s=this.service;
if (s.getMsg) {
message.error("获取文章失败",3,()=> s.getMsg=false)
}
let post=s.post;
return <Card title={post.title} bordered={true} style={{width:600}}>
<p>{post.author} {new Date(post.postdate*1000).toLocaleDateString()} </p>
<p>{post.content}</p>
</Card>
}
}
3 业务层代码如下
/src/service/post.js
import axios from ‘axios‘
import { observable } from ‘mobx‘
import store from ‘store‘
export default class PostService {
constructor() {
this.instance = axios.create({
baseURL: ‘/api/post‘,
});
}
@observable semsg = "";
@observable failsg = "";
@observable posts = []; //定义输出结果至此容器中
@observable pagination = ‘‘; //定义分页功能相关参数监控
@observable post=‘‘; //定义get 获取到的详细的页面数据
@observable getMsg=false;// 定义get 获取是否获取数据成功返回处理
pub(title, content) {
console.log(title, content)
this.instance.post(‘/pub‘, {
title, content
}, {
headers: { ‘jwt‘: store.get(‘token‘) }
}).then((response) => {
console.log(response.data),
console.log(Response.status);
this.semsg = "博文提交成功"; // 触发事件
}).catch((error) => {
console.log(error.data);
this.failsg = "博文提交失败";
})
}
getall(search) {
axios.get(‘/api/post/‘ + search).then(
response => {
console.log(response.data)
this.posts = response.data.posts; //成功的输出结果
this.pagination = response.data.pagination; //携带的相关参数
}
).catch(error=> {
console.log(error.data)
})
}
get(id){
axios.get(‘/api/post/‘+id).then(response =>{
console.log(response.data)
this.post=response.data.post;
}).catch(error => {
console.log(error.data)
this.getMsg=true;
})
}
}
结果如下
5 通过getall页面跳转至详情页面
通过getall中获取的post_id 进行跳转到localhost/get/x
import React from ‘react‘;
import { observer } from ‘mobx-react‘;
import PostService from ‘../service/post‘;
import { List, Avatar,Pagination,Link } from ‘antd‘;
import ‘antd/lib/list/style‘
import ‘antd/lib/avatar/style‘
import ‘antd/lib/pagination/style‘
@observer
export default class Getall extends React.Component{
constructor(props){
super(props);
let {location:{search}}=props;
this.service=new PostService();
this.service.getall(search);
}
handleChange(page,pageSize){
console.log(page,pageSize)
let search =‘?‘+‘page=‘+page+‘&‘+‘size=‘+pageSize;
console.log(search)
this.service.getall(search)
}
render(){
const data=this.service.posts; //获取数据列表
const pagination=this.service.pagination; //分页功能实现
return (
<div>
<List
itemLayout="horizontal"
dataSource={data}
bordered="true"
split="true"
hideOnSinglePage="true"
renderItem={item => (
<List.Item>
<List.Item.Meta
avatar={<Avatar src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1571932022162&di=f108eeab8bc4d45e6d9b85c36581f9ae&imgtype=0&src=http%3A%2F%2Fs7.sinaimg.cn%2Fmw690%2F0065sEcMzy74EYHBPMOa6%26690" />}
title={<a href={‘/get/‘+item.post_id}>{item.title}</a>}
description={item.title}
/>
</List.Item>
)}
/>
<Pagination defaultCurrent={1} total={pagination.count} pageSize={pagination.size} onChange={this.handleChange.bind(this)}/>
</div>
)
}
}
结果如下
4 高阶组件装饰器
1 基本代码概述
此处传入是一个类,返回也是一个类
function inject(Comp) {
return class extends React.Component {
render(){
return <Comp service={service} />
}
}
}
提取参数如下
function inject(Comp,service) {
return class extends React.Component{
render() {
return <Comp service={service} />
}
}
}
使用可变参数进行处理
function inject(...obj,Comp){
return class extends React.Component{
render(){
return <Comp {...obj} />
}
}
}
柯里化
function inject(obj){
function wrapper(Comp) {
return class extends React.Component{
render(){
return <Comp {...obj} />
}
}
}
return wrapper;
}
变形
function inject(obj){
return function wrapper(Comp) {
return class extends React.Component{
render(){
return <Comp {...obj} />
}
}
}
}
箭头函数变形
const inject = obj => Comp => {
return class extends React.Component{
render(){
return <Comp {...obj} />
}
}
}
函数式组件简化
const insject = obj=> Comp=> {
return props => <Comp {...obj} />
}
继续简化如下
const insject = obj=> Comp => props => <Comp {...obj} {...props} />
2 创建外置函数,用于处理service的传入问题
创建utils.js文件,和src 在同一级目录,如下
import React from ‘react‘;
const insject = obj=> Comp => props => <Comp {...obj} {...props}/>
export {insject}
3 修改登陆和注册view代码
/src/component/login.js
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
import { message } from ‘antd‘;
let service = new UserService()
import { insject } from "../utils";
@insject({service})
@observer
export default class Login extends React.Component{
handlerClick(event){
event.preventDefault(); //其默认是写一条数据提交一次,此命令用于阻止其默认提交
console.log(‘this----------‘,this) //此处的this指的是Login 实例,可将此值传入进去用于修改ret 的值来触发页面刷新
let fm=event.target.form
this.props.service.login(fm[0].value,fm[1].value,this);
}
render(){
if ( this.props.service.loggin)
return <Redirect to=‘/getall‘ />
if (this.props.service.loginerrMsg)
{
message.error(‘用户名或密码错误‘,3,()=>{
this.props.service.loginerrMsg=‘‘;
})
}
return (
<div className="login-page">
<div className="form">
<form className="register-form">
<input type="text" placeholder="邮箱" defaultValue="[email protected]"/>
<input type="password" placeholder="密码" defaultValue="demo"/>
<button onClick={this.handlerClick.bind(this)}>登录</button> {/*触发按钮*/}
<p className="message">还未注册 <Link to="/reg">请注册</Link></p>
</form>
</div>
</div>
)
}
}
/src/component/reg.js
import React from ‘react‘;
import ‘../css/login.css‘
import {Link,Redirect} from ‘react-router-dom‘;
import UserService from ‘../service/user‘
import {observer} from ‘mobx-react‘
import { message } from ‘antd‘;
import { insject } from "../utils";
const service= new UserService();
@insject({service})
@observer
export default class ?Reg???extends??React.Component??{
handleClick(event)?{
????????event.preventDefault();??//处理页面刷新问题,阻止缺省行为?
????????let?fm=event.target.form;
????????console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //获取注册信息
this.props.service.reg(fm[0].value,fm[1].value,fm[2].value)
console.log(this.props.service.regin)
????}
????render()?{
if (this.props.service.regin)
return <Redirect to=‘/about‘ />
if (this.props.service.regerrMsg){
message.error(‘注册失败,请检查相关参数是否正确‘,3,()=>this.props.service.regerrMsg=‘‘)
}
??????return??(
????????<div?className="login-page">
????????????<div??className="form">
<form className="register-form">
<input type="text" placeholder="用户名"/>
<input type="text" placeholder="邮箱"/>
<input type="password" placeholder="密码"/>
<input type="password" placeholder="确认密码"/>
<button onClick={this.handleClick.bind(this)}>注册</button> {/*触发按钮*/}
<p className="message">已经注册 <Link to="/reg">请登录</Link></p>
</form>
????????????</div>
????????</div>???????
???????)
????}??
??}
5 index.js页面添加布局
1 相关文档如下
https://ant.design/components/layout-cn/
2 具体代码如下
import React from ‘react‘;
import ReactDom from ‘react-dom‘;
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Login from ‘./component/login‘;
import Reg from ‘./component/reg‘;
import Pub from ‘./component/pub‘
import Get from ‘./component/get‘
import Getall from ‘./component/Getall‘;
import ‘antd/lib/menu/style‘
import ‘antd/lib/icon/style‘
import ‘antd/lib/layout/style‘
import { Layout, Menu,Icon } from ‘antd‘;
const { Header, Content, Footer } = Layout;
import ‘antd/lib/layout/style‘
import ‘antd/lib/menu/style‘
const Home =() => {
return (
<div>
<h2>Home</h2>
</div>
);
}
class Root extends React.Component {
render() {
return (
<Router>
<Layout>
<Header style={{ position: ‘fixed‘, zIndex: 1, width: ‘100%‘ }} >
<div className="logo" />
<Menu theme="dark"
mode="horizontal"
defaultSelectedKeys={[‘1‘]}
style={{ lineHeight: ‘65px‘ }}>
<Menu.Item key="home">
<Link to="/"><Icon type="home" /> 主页</Link>
</Menu.Item>
<Menu.Item key="login">
<Link to="/login"><Icon type="login" />登陆</Link>
</Menu.Item>
<Menu.Item key="reg">
<Link to="/reg"><Icon type="home" />注册</Link>
</Menu.Item>
<Menu.Item key="pub">
<Link to="/pub"><Icon type="home" />上传</Link>
</Menu.Item>
<Menu.Item key="getall">
<Link to="/getall"><Icon type="home" />列表查看</Link>
</Menu.Item>
<Menu.Item key="get">
<Link to="/get"><Icon type="bars" />详情页</Link>
</Menu.Item>
</Menu>
</Header>
<h1></h1>
<h1></h1>
<h1></h1>
<h1></h1>
<h1></h1>
<Content style={{ padding: ‘5px 20px‘ }}>
<div style={{ background: ‘#fff‘, padding: 30, minHeight: 50}}>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/reg" component={Reg} />
<Route path="/pub" component={Pub} />
<Route path="/getall" component={Getall} />
<Route path="/get" component={Get} />
</div>
</Content>
<Footer style={{ textAlign: ‘center‘ }}>Ant Design ?2018 Created by Ant UED</Footer>
</Layout>
</Router>
)
}
}
ReactDom.render(<Root />,document.getElementById(‘root‘));
结果如下
至此,前端页面开发完成
原文地址:https://blog.51cto.com/11233559/2446128