多人博客项目构建过程(四)

前端开发

开发环境设置

 

 

修改项目信息

打开VS工具,选择package.json文件

选择webpack.config.dev.js文件

安装依赖

$npm install
$npm install react-router
$npm install react-router-dom

 开发

前端路由

#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>
        ); 
    }
}

 

做一枚奔跑的老少年!
原文地址:https://www.cnblogs.com/xiaoshayu520ly/p/11437593.html