一 開發環境設置
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="12345@123"/>
<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="12345@123"/>
<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{
@observable 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="12345@123"/>
<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="12345@123"/>
<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="12345@123"/>
<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'));
結果如下
至此,前端頁面開發完成