前端开发
开发环境设置
修改项目信息
打开VS工具,选择package.json文件
选择webpack.config.dev.js文件
安装依赖
$npm install $npm install react-router $npm install react-router-dom
开发
前端路由
官网文档:https://reacttraining.com/react-router/web/guides/philosophy
基本例子:https://reacttraining.com/react-router/web/example/basic
#src/index.js import React from 'react'; import ReactDom from 'react-dom'; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; const Home = () => ( <div> <h2>Home</h2> </div> ); const About = () => ( <div> <h2>About</h2> </div> ); const App = () => ( <Router> <div> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> </div> </Router> ); ReactDom.render(<App />,document.getElementById('root'));
登录组件
<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>
//在src/component/login.js import React from 'react'; import ReactDom from 'react-dom'; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; import '../css/login.css' export default class Login extends React.Component{ render(){ return ( <div className="login-page"> <div className="form"> <form className="login-form"> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <button>登录</button> <p className="message">还未注册? <a href="/reg">注册用户</a></p> </form> </div> </div> ); } }
//src/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 = () => ( <div> <h2>Home</h2> </div> ); const About = () => ( <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} /> </div> </Router> ); } } ReactDom.render(<Root />,document.getElementById('root'));
//在src/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,.form button:active,.form button:focus { background: #43A047; } .form .message { margin: 15px 0 0; color: #b3b3b3; font-size: 12px; } .form .message a { color: #4CAF50; text-decoration: none; }
可以看到如下界面,(http://127.0.0.1:3000/login)
注册组件
#src/component/reg.js import React from 'react'; import {Link} from 'react-dom'; import '../css/login.css' export default class Reg extends React.Component{ render(){ return ( <div className="login-page"> <div className="form"> <form className="login-form"> <input type="text" placeholder="姓名"/> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <input type="password" placeholder="确认密码"/> <button>注册</button> <p className="message">如果已经注册 <Link to="/reg">请登录</Link></p> </form> </div> </div> ); } }
//在src/index.js添加 import Reg from './component/reg'; 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> ); } }
导航栏组件
//... class Root extends React.Component{ render(){ return ( <Router> <div> <ul> <li><Link to="/">主页</Link></li> <li><Link to="/login">登录</Link></li> <li><Link to="/reg">注册</Link></li> <li><Link to="/about">关于</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> ); } } //...
登录功能实现
import React from 'react'; import ReactDom from 'react-dom'; import '../css/login.css' export default class Login extends React.Component{ handleClick(event){ event.preventDefault(); console.log('~~~~~~~~~~~~~~~~~~'); console.log(this);//Login console.log(event); console.log(event.target);//button console.log(event.target.form); 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="login-form"> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <button onClick={this.handleClick.bind(this)}>登录</button> <p className="message">还未注册? <a href="/reg">注册用户</a></p> </form> </div> </div> ); } }
//src/component/login.js import React from 'react'; import ReactDom from 'react-dom'; import '../css/login.css'; import UserService from '../service/user'; const userService = new UserService(); export default class Login extends React.Component{ render(){ return <_Login service={userService}/>; } } class _Login extends React.Component{ handleClick(event){ event.preventDefault(); console.log('~~~~~~~~~~') let fm = event.target.form; this.props.service.login( fm[0].value,fm[1].value ); } render(){ return ( <div className="login-page"> <div className="form"> <form className="login-form"> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <button onClick={this.handleClick.bind(this)}>登录</button> <p className="message">还未注册? <a href="/reg">注册用户</a></p> </form> </div> </div> ); } }
UserService的login方法实现
devServer: { compress: true, port: 3000, publicPath: '/assets/', hot: true, inline: true, historyApiFallback: true, stats: { chunks: false }, proxy: { '/api': { target: 'http://127.0.0.1:8000', changeOrigin: true } } }
axios异步库
import axios from 'axios'; export default class UserService{ login(email,password){ console.log(email,password,'++++++') //异步调用 axios.post('/api/user/login', { 'email': email, 'password': password })/*dev server会代理*/ .then(function (response) { console.log(response); console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }) .catch(function (error) { console.log(error); }); } }
参考:https://webpack.js.org/configuration/dev-server/#devserver-proxy
//在webpack.config.dev.js中添加 devServer: { compress: true, port: 3000, publicPath: '/assets/', hot: true, inline: true, historyApiFallback: true, stats: { chunks: false }, proxy: { '/api': { target: 'http://127.0.0.1:8000', pathRewrite: {'^/api' : ''}, changeOrigin: true } } }
token持久化---LocalStorage
store.js
let store = require('store'); store.set('user','wayne'); console.log(store.get('user')); store.remove('user'); console.log(store.get('user')); console.log(store.get('user','a')); store.set('user',{name:'wayne',age:30}); console.log(store.get('user').name); store.set('school',{name:'magedu'}); store.each(function(value,key){ console.log(key,'-->',value) }); // user --> { name: 'wayne', age: 30 } // school --> { name: 'magedu' } store.clearAll(); console.log(store.get('user')); // undefined
store.addPlugin(require('store/plugins/expire'));//过期插件 store.set('token',res.data.token,(new Date()).getTime() + (8*3600*1000));
Mobx状态管理
Redux和Mobx
Mobx官网:https://mobx.js.org/
状态管理
1.同步调用
import React from 'react'; import ReactDom from 'react-dom'; class Service{ handle(n){ //同步 console.log('pending~~~~~'); for (let s=new Date();new Date()-s<n*1000;); console.log('done'); return Math.random(); } } class Root extends React.Component{ state = {ret:null} handleClick(event){ //同步返回值 let ret = this.props.Service.handle(4); } render(){ console.log('*'*20) return ( <div> <button onClick={this.handleClick.bind(this)}>触发handleClick函数</button> <span style={{color:'red'}}>{new Date().getTime()} Service的handle函数返回值是:{this.state.ret}</span> </div> ) } } ReactDom.render(<Root service={new Service()}/>,document.getElementById('root'));
2.异步调用
import React from 'react'; import ReactDom from 'react-dom'; class Service{ handle(obj){ //Promise new Promise((resolve,reject) => { setTimeout(()=>resolve('OK'),5000); }).then( value => {// obj.setState({ret:(Math.random()*100)}); } ) } } class Root extends React.Component{ state = {ret:null} handleClick(event){ //异步不能直接使用返回值 this.props.service.handle(this); } render(){ console.log('*'*20) return ( <div> <button onClick={this.handleClick.bind(this)}>触发handleClick函数</button> <span style={{color:'red'}}>{new Date().getTime()} Service的handle函数返回值是:{this.state.ret}</span> </div> ) } } ReactDom.render(<Root service={new Service()}/>,document.getElementById('root'));
3.Mobx实现
import React from 'react'; import ReactDom from 'react-dom'; import {observable} from 'mobx'; import {observer} from 'mobx-react'; class Service{ @observable ret = -1; handle(obj){ //Promise new Promise((resolve,reject) => { setTimeout(()=>resolve('OK'),2000); }).then( value => {// this.ret = (Math.random()*100); console.log(ret); } ) } } @observer //将react组件转换为响应式组件 class Root extends React.Component{ // state = {ret:null} handleClick(event){ //异步不能直接使用返回值 this.props.service.handle(this); } render(){ console.log('*'*20) return ( <div> <button onClick={this.handleClick.bind(this)}>触发handleClick函数</button> <span style={{color:'red'}}>{new Date().getTime()} Service的handle函数返回值是:{this.state.ret}</span> </div> ) } } ReactDom.render(<Root service={new Service()}/>,document.getElementById('root'));
login登录功能代码实现
//在src/service/user.js中 import axios from 'axios'; import store from 'store'; import {observable} from 'mobx'; store.addPlugin(require('store/plugins/expire')); export default class UserService{ @observable loggindin = false; //+被观察者 login(email,password){ console.log(email,password); //异步调用 axios.post('/api/user/login', { 'email': email, 'password': password })/*dev server会代理*/ .then((response) => { console.log(response.data); console.log(response.status); //+ 存储token store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000)); this.loggindin = true; //+ 修改被观察者 }) .catch( (error) => { console.log(error); }); } }
//src/component/login.js import React from 'react'; import '../css/login.css'; import UserService from '../service/user'; import {Link,Redirect} from 'react-router-dom' import {observer} from 'mobx-react'; const userService = new UserService(); export default class Login extends React.Component{ render(){ return <_Login service={userService}/>; } } @observer class _Login extends React.Component{ handleClick(event){ event.preventDefault(); let fm = event.target.form; this.props.service.login( fm[0].value,fm[1].value ); } render(){ if (this.props.service.loggedin){ return <Redirect to='/' />; //+ 跳转 } return ( <div className="login-page"> <div className="form"> <form className="login-form"> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <button onClick={this.handleClick.bind(this)}>登录</button> <p className="message">还未注册? <a href="/reg">注册用户</a></p> </form> </div> </div> ); } }
前端注册功能实现
import axios from 'axios'; import store from 'store'; import {observable} from 'mobx'; store.addPlugin(require('store/plugins/expire')); export default class UserService{ @observable loggedin = false; //+被观察者 login(email,password){ console.log(email,password); //异步调用 axios.post('/api/user/login', { 'email': email, 'password': password })/*dev server会代理*/ .then((response) => { console.log(response.data); console.log(response.status); //+ 存储token store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000)); this.loggedin = true; //+ 修改被观察者 }) .catch( (error) => { console.log(error); }); } //新增reg函数 reg(name, email, password){ console.log(email,password); axios.post('api/user/reg',{ 'eamil':email, 'password':password, 'name':name })/* dev server会代理 */ .then((response) => {//此函数需要注意this的问题 console.log(response.data); console.log(response.status); //+ 存储token store.set('token',response.data.token,(new Date).getTime()+(8*3600*1000)); //注册成功,返回token即成功登录 this.loggedin = true; //+ 修改被观察者 }) .catch((error)=>{ console.log(error); }) }
//src/component/reg.js import React from 'react'; import {Redirect} from 'react-router-dom'; import '../css/login.css' import UserService from '../service/user'; import {observer} from 'mobx-react'; const userService = new UserService(); export default class Reg extends React.Component{ render(){ return <_Reg service={userService} />; } } @observer class _Reg extends React.Component{ handleClick(event){ event.preventDefault(); let fm = event.target.form; this.props.service.reg(fm[0].value,fm[1].value,fm[2].value); } render(){ console.log('component reg!!') if(this.props.service.loggedin){ 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">如果已经注册 <a href="/login">请登录</a></p> </form> </div> </div> ); } }
Ant Design
import {List} from 'antd'; import 'antd/lib/list/style/css'; import ReactDom from 'react-dom'; ReactDom.render(<List />,mountNode);
信息显示
import axios from 'axios'; import store from 'store'; import {observable} from 'mobx'; store.addPlugin(require('store/plugins/expire')); export default class UserService{ @observable loggedin = false; //+被观察者 @observable errMsg = ''; login(email,password){ console.log(email,password,'in login function!'); //异步调用 axios.post('/api/user/login', { 'email': email, 'password': password })/*dev server会代理*/ .then((response) => { console.log(response.data); console.log(response.status); //+ 存储token store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000)); this.loggedin = true; //+ 修改被观察者 }) .catch( (error) => { console.log(error); this.errMsg = '登录失败';//+ 信息显示 }); } reg(name, email, password){ console.log(email,password,name,'in reg f unction!'); //异步调用 axios.post('api/user/reg',{ 'email':email, 'password':password, 'name':name })/* dev server会代理 */ .then((response) => {//此函数需要注意this的问题 console.log(response.data); console.log(response.status); //+ 存储token store.set('token',response.data.token,(new Date()).getTime()+(8*3600*1000)); //注册成功,返回token即成功登录 this.loggedin = true; //+ 修改被观察者 }) .catch((error)=>{ console.log(error); this.errMsg = '注册失败'//+ 信息显示 }); }
import React from 'react'; import '../css/login.css'; import UserService from '../service/user'; import {Link,Redirect} from 'react-router-dom' import {observer} from 'mobx-react'; //新增 import {message} from 'antd'; import 'antd/lib/message/style'; const userService = new UserService(); export default class Login extends React.Component{ render(){ return <_Login service={userService}/>; } } @observer class _Login extends React.Component{ handleClick(event){ event.preventDefault(); let fm = event.target.form; this.props.service.login( fm[0].value,fm[1].value ); } render(){ console.log('in login.js') if (this.props.service.loggedin){ return <Redirect to='/about' />; //+ 跳转 } //新增 if (this.props.service.errMsg){ message.info(this.props.service.errMsg,3, ()=> SetTimeout(()=>this.props.service.errMsg=''),1000); } return ( <div className="login-page"> <div className="form"> <form className="login-form"> <input type="text" placeholder="邮箱"/> <input type="password" placeholder="密码"/> <button onClick={this.handleClick.bind(this)}>登录</button> <p className="message">还未注册? <a href="/reg">注册用户</a></p> </form> </div> </div> ); } }
import React from 'react'; import {Redirect} from 'react-router-dom'; import '../css/login.css' import UserService from '../service/user'; import {observer} from 'mobx-react'; //新增 import {message} from 'antd'; import 'antd/lib/message/style'; const userService = new UserService(); export default class Reg extends React.Component{ render(){ return <_Reg service={userService} />; } } @observer class _Reg extends React.Component{ handleClick(event){ event.preventDefault(); let fm = event.target.form; this.props.service.reg(fm[0].value,fm[1].value,fm[2].value); } render(){ console.log('component reg!!') if(this.props.service.loggedin){ return <Redirect to='/about'/>; } //新增 if(this.props.service.errMsg){ message.info(this.props.service.errMsg,3,()=>{ setTimeout(()=>this.props.service.errMsg='',1000); }) } 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">如果已经注册 <a href="/login">请登录</a></p> </form> </div> </div> ); } }