I. development environment settings
1 installation package environment
The package is as follows
Links: https://pan.baidu.com/s/1C-ZY9rWU-8ZugE4EwVveWw
Extraction code: 744p
Related react introduction links are as follows
https://blog.51cto.com/11233559/2443713
Unzip and modify the directory to blog without special instructions. js files are placed in src directory.
2 modify relevant information
1 modify project information
2. Modify the reverse generation and local listening ports
The back-end service ip address of this environment is 192.168.1.200, and the back-end python listening port is 80.
3 install software
npm i
Launch and view
npm start
Function development of second login module
1 front end routing configuration
This time, use react router to configure routes
Basic example
https://reacttraining.com/react-router/web/example/basic
Official documents
https://reacttraining.com/react-router/web/guides/quick-start
According to the official example, modify src/index.js as follows
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'));
The results are as follows
Route is responsible for static routing
Path is a matching path, no path always matches.
Component is the target component.
exact: Boolean value. true requires the path to match exactly.
Strict: Boolean value, strict matching is required when true, but the url string can be its own string.
When the address changes, the Router component will match the path, and then use the matching component to render.
2. Log in to the front view layer
1 global CSS configuration
Add CSS directory and create global CSS file 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; }
as follows
2. Implementation of view layer of login module
Building react component under component directory
Login template
https://codepen.io/colorlib/pen/rxddKy?q=login&limit=all&type=type-pens
Add the component directory under src.
The HTML login template is as follows
<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>
Use this HTML template to build components
Be careful:
When moving to the React component, change the class attribute to ClassName
All labels, must be closed
login.js create
Create login.js login component in component directory
Use the login section of the HTML template above to move to the render function.
as follows
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="mailbox"/> <input type="password" placeholder="Password"/> <button>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
Add the route in index.js as follows
import React from 'react'; import ReactDom from 'react-dom'; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; import Login from './component/login' //Introducing objects 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} /> {/*This is mainly to jump to the login object.*/} </div> </Router> ) } } ReactDom.render(<Root />,document.getElementById('root'));
give the result as follows
Import style sheets as follows
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="mailbox"/> <input type="password" placeholder="Password"/> <button onClick={event =>console.log(event)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
give the result as follows
The default data passed in the page is from data
3 get trigger data
Define handlerClick function in src/component/login.js to get the data generated by trigger event
Each filling in above will lead to page refresh, rather than refresh after clicking submit. To prevent page refresh, in fact, to prevent submission, you can use event.preventDefault() to prevent automatic submission of the page.
How to get the mailbox and password
event.target.from returns the form where the button is located, which can be regarded as an array.
fm[0].value and fm[1].value are the values of the text box
How to use the UserServie instance in the login component:
1 initialize directly in the Login constructor
2 in props
The relevant codes are as follows
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(); //Its default is to write a data submission once, which is used to prevent its default submission console.log('mailbox',event.target.form[0].value) // This is used to obtain the login information of related users. console.log('Password',event.target.form[1].value) } render(){ return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="mailbox"/> <input type="password" placeholder="Password"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
give the result as follows
The data submitted by the form can be obtained through the above event.target.form[1].value
3. view implementation of registration interface
1 basic page implementation
Create reg.js in component to register function
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} />; {/*Pass the service here. In the later stage, you can use props.service.xxx to complete the data injection operation.*/} } } class _Reg extends React.Component { handleClick(event) { event.preventDefault(); //Handle page refresh and block default behavior let fm=event.target.form; console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //Get registration information } render() { console.log('++++++++++++++++++++++++') return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="Full name" /> <input type="text" placeholder="mailbox" /> <input type="password" placeholder="Password" /> <input type="password" placeholder="Confirm password" /> <button onClick={this.handleClick.bind(this)}>register</button> <p className="message">If registered <Link to="login">Please login.</Link></p> {/*Here for jump*/} </form> </div> </div> ) } }
Add routing
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'));
give the result as follows
The above contents filled in the form can be obtained directly in fm[x].value
4navigation bar components
Add navigation bar in index.js to facilitate the switching between pages
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> {/*Navigation bar related*/} <li><Link to="/">homepage</Link></li> <li><Link to="/about">about</Link></li> <li><Link to="/reg">register</Link></li> <li><Link to="/login">Sign in</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'));
give the result as follows
5 synchronous and asynchronous
1 synchronization
Simulated sleep
d1=new Date(); for (var d=new Date();(new Date())-d <1000;);// This is equivalent to sleep processing console.log('------------') d2=new Date(); console.log(d2-d1)
give the result as follows
Modification of login code
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(); //Its default is to write a data submission once, which is used to prevent its default submission // console.log('mailbox ', event.target.form[0].value) / / used here to obtain the login information of related users. // console.log('password ', event.target.form[1].value) console.log('this----------',this) //this here refers to the Login instance, which can be passed in to modify the ret value to trigger page refresh. let fm=event.target.form this.service.login(fm[0].value,fm[1].value,this); //This is used to transfer the current login and related form data to the backend service layer. console.log(this.state.ret) } render(){ if (this.state.ret != -1 ){ // If there is any change here, its status will be refreshed. console.log('ret',this.state.ret) //Print refresh results } return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="mailbox" defaultValue="12345@123"/> <input type="password" placeholder="Password" defaultValue="demo"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
The relevant codes are as follows
import axios from 'axios' export default class UserSerive{ login(email,password,obj){ for (var d=new Date();(new Date())-d <10000;);// This is equivalent to sleep processing console.log('12433645645765') console.log(email,password,obj) } }
As a result, the browser directly pauses when requesting data, and other related pages cannot be refreshed or clicked.
2 asynchronous
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') } }
The result here is that its email,password and 'Userservice' are printed immediately, but its timeout and subsequent printing lag by 10s. However, in the process of 10s, its page can be clicked and its current business execution is not blocked.
obj.setState({'ret':parseInt(Math.random()*100)}) used here to generate random integers
2 Promise
The official website code is as follows
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()
give the result as follows
export default class UserSerive{ login(email,password,obj){ new Promise((resolve,reject) => setTimeout( () => { console.log('timeout ........'); resolve('ok') //Call here to execute the code in then },5*1000)).then(value => obj.setState({'ret':parseInt(Math.random()*100)}), console.log('then-------------') ) console.log(email,password,'Userobject') } }
The result here is to print email,password and 'userobject' for 5 seconds before relevant timeout output and corresponding rendering operation. Because the page is changed, DOM rendering will not be performed.
The test code is as follows
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()
The results are as follows: the result printed here is 124234523523534564, and then the content in then is output after timeout. This indicates that the above timeout does not block the operation of the program itself, and this is the asynchronous call mode. It does not affect the next data processing of the current request
3 axios
axios is a promise based HTTP asynchronous library, which can be used in browsers or nodejs.
Use axios to initiate asynchronous call to complete data submission of post and get methods. Please refer to the official website example.
http://www.axios-js.com/zh-cn/docs/
install
npm i axios
Import
import axios from 'axios'
The basic examples are as follows
Basic GET implementation
axios.get('/user', { //The user here is the url of the api, and the absolute path is specified. params: { //Here is the value passed ID: 12345 } }) .then(function (response) { //Here is the return value of the request success console.log(response); }) .catch(function (error) { //Here is the return value of the failure console.log(error); });
Basic POST implementation
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
6 implementation of login interface
The specific code is as follows
import { comparer } from "mobx"; import axios from 'axios' // import { object } from "prop-types"; // import { resolve } from "dns"; //Handling of user logic export default class UserService{ login(email,password,obj) { axios.post('/api/user/login', { 'email': email, 'password': password }) .then(function (response) { //Successful operation console.log(response,'==================='); console.log(response.data) console.log(response.status); obj.setState({'ret':parseInt(Math.random()*100)}) //When it returns to success, change the state and enter the rendering dom. }) .catch(function (error) { //Failed action console.log(error); }); console.log(email,password,'UserService')//How to transmit, what to transmit, what to return and how to return } }
The front-end page is implemented as follows
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(); //Its default is to write a data submission once, which is used to prevent its default submission // console.log('mailbox ', event.target.form[0].value) / / used here to obtain the login information of related users. // console.log('password ', event.target.form[1].value) console.log('this----------',this) //this here refers to the Login instance, which can be passed in to modify the ret value to trigger page refresh. let fm=event.target.form this.service.login(fm[0].value,fm[1].value,this); } render(){ if (this.state.ret !=-1 ) //This is used to judge whether to jump to about page directly when it is not - 1. return <Redirect to='/about' /> return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="mailbox" defaultValue="12345@123"/> <input type="password" placeholder="Password" defaultValue="demo"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
The defaultValue in the above is handled for easy login.
The data obtained are as follows
7 localStorage and expiration implementation
Use the store to write to the local storage of the client and use its own plug-in to handle the expiration mechanism
Related official website
https://github.com/marcuswestin/store.js/
Expired plug-in
The relevant expiration codes are as follows
https://github.com/marcuswestin/store.js/blob/master/plugins/expire_test.js
Add out of date plug-ins and configurations
store.addPlugin(require('store/plugins/expire'))
Configuration overdue
store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));
8 mobx status management
1 demand
onClick of a component triggers the event response function, which will call the background service, but the background service is quite time-consuming. When the processing is completed, the rendering operation of the component needs to be caused.
To render a component, you need to change the props or state of the component
1 synchronous call
Temporarily modify index.js as follows
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;) //This is the synchronous blocking model console.log('output') 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)}> Click trigger button </button> <span style={{color:'red'}}> {new Date().getTime()} {this.state.ret} </span> </div>) } } ReactDom.render(<Root service={ new Service() }/>,document.getElementById('root'));
The result is that the page is refreshed after 10 seconds, but it cannot click other pages during this period.
2 asynchronous call
Idea 1: use setTimeout
There are two problems in using setTimeout
1 cannot pass parameters to the internal function to be executed, such as Root instance
2. The return value of delayed function is obtained repeatedly, so Root cannot be notified.
Idea 2: promise asynchronous execution
promise is executed asynchronously. If the execution is successful, call the callback.
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(()=> //Success here, return to this value resolve('ok') ,5000) }).then(value => { obj.setState({'ret':parseInt(Math.random()*1000)}) }) } } class Root extends React.Component{ state={'ret':-100} handlerClink(){ console.log('trigger') this.props.service.handler(this) } render(){ return (<div> <button onClick={this.handlerClink.bind(this)}> Click trigger button </button> <span style={{color:'red'}}> {new Date().getTime()} {this.state.ret} </span> </div>) } } ReactDom.render(<Root service={ new Service() }/>,document.getElementById('root'));
give the result as follows
In the process of the event being called, the above method does not affect the click of the page and does not block the normal processing of the page.
3 Mobx implementation
observable decorator: set the observed
Observer decorator: set observer
1 mobx + Promise implementation code
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)}> Click trigger </button> <span style={{color:'red'}} > {new Date().getTime()} {this.props.service.ret} </span> </div> } } ReactDom.render(<Root service={new Service() } />,document.getElementById('root'));
The basic conclusion is the same as the above, and its clicking will not cause page problems, thus realizing the purpose of asynchronous request.
2 mobx + axis code implementation
login is triggered to the about page as follows
The code in src/service/user.js is modified as follows
import axios from 'axios' import {observable} from 'mobx' import store from 'store' store.addPlugin(require('store/plugins/expire')) //Load out of date plug-ins, return an object here //Handling of user logic export default class UserService{ @observable loggin=0; //The observed object has been observed. Once the value changes, the observer will know. login(email,password) { axios.post('/api/user/login', { 'email': email, 'password': password }) .then( (response) => { //The problem of this is solved by arrow function. console.log(response,'==================='); console.log(response.data) console.log(response.status); //obj.setState({ret:1000}) / / state trigger causes change store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));//getTime gets time, but it's milliseconds this.loggin = Math.random() * 100; //Modified value console.log(this.loggin) }) .catch( (error) => { //Failed action console.log(error); }); //for (var d=new Date();(new Date())-d < 10 * 1000;); / / here is synchronization console.log(email,password,'UserService')//How to transmit, what to transmit, what to return and how to return } }
The result of src/component/login.js is as follows
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(); //Its default is to write a data submission once, which is used to prevent its default submission console.log('this----------',this) //this here refers to the Login instance, which can be passed in to modify the ret value to trigger page refresh. 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="mailbox" defaultValue="12345@123"/> <input type="password" placeholder="Password" defaultValue="demo"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
The overall results are as follows
9. Perfect registration interface
1 Parameter deconstruction
let a=1,b=2,c=3 var obj={a,b,c} console.log(obj)
give the result as follows
2. Perfect registration interface
The configuration in src/service/user.js is as follows
import axios from 'axios' import {observable} from 'mobx' import store from 'store' store.addPlugin(require('store/plugins/expire')) //Load out of date plug-ins, return an object here //Handling of user logic export default class UserService{ @observable loggin=0; //The observed object has been observed. Once the value changes, the observer will know. @observable regin=0; //Define the observed object of login login(email,password) { axios.post('/api/user/login', { 'email': email, 'password': password }) .then( (response) => { //The problem of this is solved by arrow function. console.log(response,'==================='); console.log(response.data) console.log(response.status); //obj.setState({ret:1000}) / / state trigger causes change store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));//getTime gets time, but it's milliseconds this.loggin = Math.random() * 100; //Modified value console.log(this.loggin) }) .catch( (error) => { //Failed action console.log(error); }); //for (var d=new Date();(new Date())-d < 10 * 1000;); / / here is synchronization console.log(email,password,'UserService')//How to transmit, what to transmit, what to return and how to return } reg(name,email,password){ axios.post('/api/user/reg',{ name,email,password} ).then((response)=> { console.log(response.data); this.regin=parseInt(Math.random()*100); //Trigger change store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));//getTime gets time, but it's milliseconds }).catch((error)=> { console.log(error.data); }) } }
The configuration in src/component/reg.js is as follows
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} />; {/*Pass the service here. In the later stage, you can use props.service.xxx to complete the data injection operation.*/} } } @observer class _Reg extends React.Component { handleClick(event) { event.preventDefault(); //Handle page refresh and block default behavior let fm=event.target.form; console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //Get registration information 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="User name"/> <input type="text" placeholder="mailbox"/> <input type="password" placeholder="Password"/> <input type="password" placeholder="Confirm password"/> <button onClick={this.handleClick.bind(this)}>register</button> {/*Trigger button*/} <p className="message">Already registered <Link to="/reg">Please login</Link></p> </form> </div> </div> ) } }
10 add information prompt
In web page development, there are many prompt messages, no matter whether the operation is successful or not. At present, the messages are output from the console, which can not be seen by users. Use the message component of Antd to display friendly message prompts.
1 temporarily modify the index.js page to get the prompt information
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('Trigger construction') } class Root extends React.Component{ render(){ return (<div> <button type="prmary" onClick={info}>Click trigger</button> </div>) } } ReactDom.render(<Root />,document.getElementById('root'));
give the result as follows
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 here is the display delay of 5 } class Root extends React.Component{ render(){ return (<div> <button type="prmary" onClick={info}>Click trigger</button> </div>) } } ReactDom.render(<Root />,document.getElementById('root'));
2 trigger multiple data at the same time
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}>Click trigger</button> </div>) } } ReactDom.render(<Root />,document.getElementById('root'));
give the result as follows
3. Business addition prompt
index.js code restore
The code is modified as follows
import axios from 'axios' import {observable} from 'mobx' import store from 'store' store.addPlugin(require('store/plugins/expire')) //Load out of date plug-ins, return an object here //Handling of user logic export default class UserService{ @observable loggin=0; //The observed object has been observed. Once the value changes, the observer will know. @observable regin=0; //Define the observed object of login @observable loginerrMsg=''; //Define the output of login error @observable regerrMsg=''; //Define the output result of registration error login(email,password) { axios.post('/api/user/login', { 'email': email, 'password': password }) .then( (response) => { //The problem of this is solved by arrow function. console.log(response,'==================='); console.log(response.data) console.log(response.status); //obj.setState({ret:1000}) / / state trigger causes change store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));//getTime gets time, but it's milliseconds this.loggin = Math.random() * 100; //Modified value console.log(this.loggin) }) .catch( (error) => { //Failed action console.log(error); this.loginerrMsg=true; //Triggered when an error occurs }); //for (var d=new Date();(new Date())-d < 10 * 1000;); / / here is synchronization console.log(email,password,'UserService')//How to transmit, what to transmit, what to return and how to return } reg(name,email,password){ axios.post('/api/user/reg',{ name,email,password} ).then((response)=> { console.log(response.data); this.regin=parseInt(Math.random()*100); //Trigger change store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000));//getTime gets time, but it's milliseconds }).catch((error)=> { this.regerrMsg=true; //Trigger when an error occurs console.log(error.data); }) } }
The src/component/login.js code is as follows
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(); //Its default is to write a data submission once, which is used to prevent its default submission console.log('this----------',this) //this here refers to the Login instance, which can be passed in to modify the ret value to trigger page refresh. 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('Wrong user name or password',3,()=>{ this.props.service.loginerrMsg=''; }) } return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="mailbox" defaultValue="12345@123"/> <input type="password" placeholder="Password" defaultValue="demo"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</Link></p> </form> </div> </div> ) } }
The src/component/reg.js code is as follows
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} />; {/*Pass the service here. In the later stage, you can use props.service.xxx to complete the data injection operation.*/} } } @observer class _Reg extends React.Component { handleClick(event) { event.preventDefault(); //Handle page refresh and block default behavior let fm=event.target.form; console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //Get registration information 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('Registration failed, please check whether the relevant parameters are correct',3,()=>this.props.service.regerrMsg='') } return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="User name"/> <input type="text" placeholder="mailbox"/> <input type="password" placeholder="Password"/> <input type="password" placeholder="Confirm password"/> <button onClick={this.handleClick.bind(this)}>register</button> {/*Trigger button*/} <p className="message">Already registered <Link to="/reg">Please login</Link></p> </form> </div> </div> ) } }
give the result as follows
Function development of three blog modules
1 interface rules related
/post/put POST submits the title and content of the blog post, and successfully returns the post Ou ID of JSON.
/post/id GET returns the post details. Return JSON's post_id, title, author, author_id, post date (timestamp), content
/post/GET returns the list of Posts
2 upload blog related configuration
1 related documents
https://ant.design/components/layout-cn/
2 front end routing configuration
The code in index.js is as follows
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="/">homepage</Link></li> <li><Link to="/about">about</Link></li> <li><Link to="/reg">register</Link></li> <li><Link to="/login">Sign in</Link></li> <li><Link to="/pub">Blog upload</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 back end service configuration
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="Blog submitted successfully"; // Trigger event }).catch((error)=> { console.log(error.data); this.msg="Failed to submit blog"; }) } }
4 rendering page configuration
From form component, layout is vertical, and onsubmit submission. Note that this submission is the form itself.
From item table one way, label set the title of the control, labelCol set the width of the label, wrapperCol is the width occupied by the label, these are the width of the grid system.
INput input field, placeholder prompt character
TextArea textbox, rows
Button button. htmlType uses the type value in HTML. Submit is the submit button will trigger the submit behavior, but this behavior will be blocked in 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="Title" wrapperCol={{span:20}} labelCol={{span:2}}> <Input /> </Form.Item> <Form.Item label="content" wrapperCol={{span:20}} labelCol={{span:2}}> <TextArea rows={28}/> </Form.Item> <Form.Item wrapperCol={{span:4,offset:10}}> <Button type="primary" htmlType="submit" >Release</Button> </Form.Item> </Form> ); } }
5 the results are as follows
3. View the related configuration and getall of the blog list
1 related documents
ISTIS is needed here. The relevant links are as follows
https://ant.design/components/list-cn/ https://ant.design/components/form-cn/ https://ant.design/components/input-cn/
2 test page data acquisition
Configure render page
Create the Getall.js file in component as follows
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> } }
Add it to index.js and the result is as follows
Write http: / / localhost / list? Page = 1 & size = 10 in the input box as follows
As can be seen from the above figure, the props contains the content of the page input box, which is extracted as follows
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) //get data } render(){ return <h1>Getall</h1> } }
give the result as follows
3 display layer code implementation
/The code in src/component/getall.js is as follows
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; //Get data list const pagination=this.service.pagination; //Paging function implementation 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. The logic layer code is as follows
/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 = []; //Define output results in this container @observable pagination = ''; //Define parameter monitoring related to paging function 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 = "Blog submitted successfully"; // Trigger event }).catch((error) => { console.log(error.data); this.failsg = "Failed to submit blog"; }) } getall(search) { axios.get('/api/post/' + search).then( response => { console.log(response.data) this.posts = response.data.posts; //Successful output this.pagination = response.data.pagination; //Relevant parameters carried } ).catch(error=> { console.log(error.data) }) } }
give the result as follows
4 details page get configuration
1 get id data
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>) } }
The results of adding it to index.js are as follows
As we know above, the id acquisition is still completed through pathname, and the specific code is as follows
2. The code of view layer is as follows
/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('/') // Get ID this.service.get(id) //Asynchronous value transfer to back end } render(){ let s=this.service; if (s.getMsg) { message.error("Failed to get article",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. Business layer code is as follows
/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 = []; //Define output results in this container @observable pagination = ''; //Define parameter monitoring related to paging function @observable post=''; //Define the detailed page data obtained by get @observable getMsg=false;// Define whether get gets data successfully and returns to processing 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 = "Blog submitted successfully"; // Trigger event }).catch((error) => { console.log(error.data); this.failsg = "Failed to submit blog"; }) } getall(search) { axios.get('/api/post/' + search).then( response => { console.log(response.data) this.posts = response.data.posts; //Successful output this.pagination = response.data.pagination; //Relevant parameters carried } ).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; }) } }
give the result as follows
5 jump to details page through getall page
Jump to localhost/get/x through the post_id obtained in getall
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; //Get data list const pagination=this.service.pagination; //Paging function implementation 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> ) } }
give the result as follows
4 high level component decorator
1 basic code overview
Here, a class is passed in and a class is returned.
function inject(Comp) { return class extends React.Component { render(){ return <Comp service={service} /> } } }
The extraction parameters are as follows
function inject(Comp,service) { return class extends React.Component{ render() { return <Comp service={service} /> } } }
Processing with variable parameters
function inject(...obj,Comp){ return class extends React.Component{ render(){ return <Comp {...obj} /> } } }
currying
function inject(obj){ function wrapper(Comp) { return class extends React.Component{ render(){ return <Comp {...obj} /> } } } return wrapper; }
deformation
function inject(obj){ return function wrapper(Comp) { return class extends React.Component{ render(){ return <Comp {...obj} /> } } } }
Arrow function deformation
const inject = obj => Comp => { return class extends React.Component{ render(){ return <Comp {...obj} /> } } }
Functional component simplification
const insject = obj=> Comp=> { return props => <Comp {...obj} /> }
Continue to simplify as follows
const insject = obj=> Comp => props => <Comp {...obj} {...props} />
2. Create an external function to handle the incoming problem of service
Create the utils.js file in the same directory as src, as follows
import React from 'react'; const insject = obj=> Comp => props => <Comp {...obj} {...props}/> export {insject}
3 modify the login and registration view code
/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(); //Its default is to write a data submission once, which is used to prevent its default submission console.log('this----------',this) //this here refers to the Login instance, which can be passed in to modify the ret value to trigger page refresh. 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('Wrong user name or password',3,()=>{ this.props.service.loginerrMsg=''; }) } return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="mailbox" defaultValue="12345@123"/> <input type="password" placeholder="Password" defaultValue="demo"/> <button onClick={this.handlerClick.bind(this)}>Sign in</button> {/*Trigger button*/} <p className="message">Not yet registered <Link to="/reg">Please register</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(); //Handle page refresh and block default behavior let fm=event.target.form; console.log(fm[0].value,fm[1].value,fm[2].value,fm[3].value) //Get registration information 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('Registration failed, please check whether the relevant parameters are correct',3,()=>this.props.service.regerrMsg='') } return ( <div className="login-page"> <div className="form"> <form className="register-form"> <input type="text" placeholder="User name"/> <input type="text" placeholder="mailbox"/> <input type="password" placeholder="Password"/> <input type="password" placeholder="Confirm password"/> <button onClick={this.handleClick.bind(this)}>register</button> {/*Trigger button*/} <p className="message">Already registered <Link to="/reg">Please login</Link></p> </form> </div> </div> ) } }
5 add layout to index.js page
1 relevant documents are as follows
https://ant.design/components/layout-cn/
2 the specific code is as follows
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" /> homepage</Link> </Menu.Item> <Menu.Item key="login"> <Link to="/login"><Icon type="login" />Land</Link> </Menu.Item> <Menu.Item key="reg"> <Link to="/reg"><Icon type="home" />register</Link> </Menu.Item> <Menu.Item key="pub"> <Link to="/pub"><Icon type="home" />upload</Link> </Menu.Item> <Menu.Item key="getall"> <Link to="/getall"><Icon type="home" />List view</Link> </Menu.Item> <Menu.Item key="get"> <Link to="/get"><Icon type="bars" />Details page</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'));
give the result as follows
So far, the front-end page development is completed