乐趣区

ReactNodeExpress搭建一个前后端demo

1. 简述

  • demo:以前用过原生 JS 写计算器,这里我想要 react 来写,并且用数据库记录每次计算公式和结果,并且可发请求获取
  • 后台部分:建立数据库后,通过 Node.js 的 express 框架写接口操作数据库
  • 前端页面:通过 react 的 router 控制路由编写,然后通过 axios 发送请求给后台

2.Express 简介和上手

express 官方链接,具体的通过对官方文档的学习还是比较容易上手的,这里我就简要说明

2.1 新建 express 项目

webstorm 可以直接点击 newporject 来选择 expressApp

2.2 项目结构与路由挂载

├── app.js # 应用的主入口
├── bin  # 启动脚本
├── node_modules # 依赖的模块
├── package.json # node 模块的配置文件
├── public # 静态资源,如 css、js 等存放的目录
├── routes # 路由规则存放的目录
└── views # 模板文件存放的目录

2.3 路由

路由写到 routes 下面

var express = require('express');
var router = express.Router();
router.get('/list', function(req, res, next) {
//pool.query 是数据库的连接池下面会说到
    pool.query('SELECT * FROM counter;', function (err, rows, fields) {if (err) throw err;
        console.log(rows)
        res.json(rows)

    })
});
router.post('/add', function(req, res, next) {console.log(req.body)
    //var mysqltl='INSERT INTO counter(id,counter, time) VALUES(\''+req.body.counter+'\','+'now()'+');'var mysqltl=`INSERT INTO counter(counter, time) VALUES('${req.body.counter}',now());`
    console.log(mysqltl)
    pool.query(mysqltl, function (err, rows, fields) {if (err) throw err;
        console.log(rows)
        res.json(rows)

    })
});

2.4 允许跨域请求设置

在 app.js 里面添加

app.all('*', function (req, res, next) {res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    res.header('Content-Type', 'application/json;charset=utf-8');
    next();});

2.5express 对数据库的连接

2.5.1. 通过 createConnection 直接创建连接,这种方式需要去释放连接,不建议使用

var mysql = require('mysql');
var connection = mysql.createConnection({
    host     : 'localhost',
    user     : 'root',
    password : '******',
    database : 'mytest'// 你的数据库名字
})
connection.connect()

2.5.2. 通过连接池连接,这样可以出来高并发的情况,也不用去释放连接

var mysql = require('mysql');
var pool  = mysql.createPool({
    connectionLimit : 100,// 最多处理多少连接次数
    host     : 'localhost',
    user     : 'root',
    password : '****',
    database : 'mytest'
});

2.6 运行程序

3. 数据库建立,与请求

  1. 这应该没什么好说明的,根据自己的情况建表就完事了
  2. 建立好数据库后通过 express 里面的路由页面那里接受前台发的请求,并且通过 sql 语句操作数据库
  3. 这里前台的请求我用的 axios 发送没有的可以 cnpm install axios –save
             axios({
                    method: 'post',
                    headers:{'Content-type':'application/json'},
                    url: 'http://localhost:3000/counter/add',
                    data: {counter: input+"="+value,}
                }).then(function (response) {console.log(response);
                    })
                    .catch(function (error) {console.log(error);
                    });

4.react 前台页面的搭建

4.1App.js: 通过 react 的 router 控制界面路由,没有按照可以 cnpm install react-router-dom –save

import React, {Component} from 'react';
import CounterView from './Pages/CounterView/index';
import CounterHistory from './Pages/CounterHistory/index';
import Login from './Pages/Login/index';
import {HashRouter,Router,Route,Switch,Link,BrowserRouter} from 'react-router-dom';
import './App.css';


class App extends Component {render() {
    return (
      <div>
          <BrowserRouter>
              <Switch>
                  <Route path="/" component={Login} exact/>
                  <Route path="/counter" component={CounterView} />
                  <Route path="/counterHistory" component={CounterHistory} />
              </Switch>
              <ul id="menu">
                  <li><Link to='/'>Home</Link></li>
                  <li><Link to='/counter'>Counter</Link></li>
                  <li><Link to='/counterHistory'>History</Link></li>
              </ul>
          </BrowserRouter>

      </div>
    );
  }
}

export default App;

4.2 写法是通过写一个方便灌入数据的 button 组件,通过事先定义好的数组去动态生成界面

4.3 效果图与核心代码

//counterview
import React, {Component} from 'react';
import MyButton from '../../components/MyButton/index';
import {BUTTON_VALUE} from '../../Utils/Enum';
import styles from './index.less';
import axios from 'axios';

class CounterView extends Component {constructor(props) {super(props);
        this.state = {inputValue:"",};
    }



    getButtonArr = (value=[]) => {var ButtonArr=[];
        value.forEach((outval)=> {outval.forEach((inval)=> {ButtonArr.push({value:inval})
            })
        })
        return ButtonArr;
    }


       count=()=>{
            var input = this.state.inputValue
            try{var value = eval(input).toFixed(2);
                const _this=this;
                axios({
                    method: 'post',
                    headers:{'Content-type':'application/json'},
                    url: 'http://localhost:3000/counter/add',
                    data: {counter: input+"="+value,}
                }).then(function (response) {console.log(response);
                    })
                    .catch(function (error) {console.log(error);
                    });
                return value;
            }catch(err){alert("表达式错误")
            }
        }


    getValue=(e)=>{
        var newInputValue=this.state.inputValue;
        var id=e.target.innerText;
        if(id !== "clear" && id !== "back" && id !== "equal"&&id!=="sign") {newInputValue = this.state.inputValue+id;}
        if(id === "=") {var value = this.count();
            newInputValue=value;
        }
        if(id === "clear") {newInputValue="";}
        if(id === "back") {newInputValue = this.state.inputValue.substring(0, this.state.inputValue.length - 1);
        }
        if(id === "√"){var value = this.count();
            if(value){newInputValue = Math.sqrt(value);
            }else{newInputValue="";}

        }
        this.setState({inputValue:newInputValue,})
    }
    changeValue=(e)=>{
        var newInputValue =e.target.value;
        console.log(newInputValue)
        this.setState({inputValue:newInputValue,})
    }

    render() {var ButtonArr = this.getButtonArr(BUTTON_VALUE)
        return (
            <div className="box1" >
                <input className="input" type="text" value={this.state.inputValue} onChange={(e)=>this.changeValue(e)}/>
                <div   onClick={(e)=>this.getValue(e)}>
                    <MyButton data={ButtonArr}  width="50px" height="50px"/>{/* 事件委托加载 mybutton 上无效 */}
                </div>

            </div>
        )
    }
}

export default CounterView;
import React, {Component} from 'react';
class MyButton extends Component {render() {
        return (
            <div >
                {this.props.data.map(data=><button value={data.value} key={data.value} style={{width:this.props.width,height:this.props.height}}>{data.value}</button>)}
            </div>
        );
    }
}

export default MyButton;
import React, {Component} from 'react';
import axios from 'axios';
import moment from 'moment';
import './index.less';

class CounterHistory extends Component {constructor(props) {super(props);
        this.state = {data:[],
        };
    }

    componentDidMount() {this.getdata();
    }

    getdata=()=>{
        const _this=this;
        axios.get('http://localhost:3000/counter')
            .then(function (response) {console.log(response)
                _this.setState({data:response.data,});
            })
            .catch(function (error) {console.log(error);

            })
    }

    del=(e)=>{
        const _this=this;
        const id=e.target.id;
        axios({
            method: 'post',
            headers:{'Content-type':'application/json'},
            url: 'http://localhost:3000/counter/del',
            data: {id: id,}
        }).then(function (response) {_this.getdata();
        }).catch(function (error) {console.log(error);
        });
    }



    changeValue=(e)=>{ }

    render() {
        var data=this.state.data;
        console.log(data)
        return (
            <div className="box1">
                <div className="box">
                    <div><span className="index">index</span>
                        <span className="eval"> 历史计算 </span>
                        <span className="time"> 计算时间 </span>
                        <span> 操作 </span>
                    </div>
                    {data.map((data,index)=>
                        <div key={data.time}>
                            <span className="index">{index+1}</span>
                            <span className="eval">{data.counter}</span>
                            <span className="time">{moment(data.time).format('YYYY-MM-DD HH:mm:ss')}</span>
                            <button id={data.id} onClick={event => this.del(event)}> 删除 </button>
                        </div>)}
                </div>
            </div>

        )
    }
}

export default CounterHistory;
退出移动版