react+express+mongodb实践

写了一小段时间的react和antd了,突然想把遇到的问题以及面试题都整理一下,然后就想到了react和express,何不做一个小网站把他们规整起来呢?小网站使用react+react-router+antd+express+mongodb+redux,说是一个全家桶一点都不过分。简洁的记录一下此次行动。
一、搭建react环境,这个就不多说了,然后将react-router、antd都添加进来(这个要是不会,回炉重造吧)
二、该写的组件,该配的router都搞好,坐等接数据
三、将express添加到项目中来。首先在根目录(和src同级)新增一个server文件夹,新建package.json:

{
        "name": "server",
        "version": "1.0.0",
        "description": "server config",
        "main": "server.js",
        "author": "luffy",
        "license": "MIT",
        "dependencies": {
          "babel-cli": "^6.26.0",
          "babel-preset-es2015": "^6.24.1",
          "body-parser": "^1.18.2",
          "express": "^4.16.3",
          "mongoose": "^5.0.16"
         },
        "scripts": {
          "start": "nodemon ./server.js",
          "build": "babel ./server.js --out-file server-compiled.js",
          "serve": "node server-compiled.js"
        }
  }

PS:这里为了让后台的代码变化后也会自动更新,需要全局安装nodemon,npm install nodemon -g
四、在server文件夹下新建server.js:

const express = require('express');
  const bodyParser = require('body-parser');

  const app = express();
  // 给app配置bodyParser中间件
  // 通过如下配置再路由种处理request时,可以直接获得post请求的body部分
  app.use(bodyParser.urlencoded({ extended: true }));
  app.use(bodyParser.json());
  // 注册路由
  const router = express.Router();
  // 路由中间件
  router.use((req, res, next) => {
    // 任何路由信息都会执行这里面的语句
    console.log('this is a api request!');
    // 把它交给下一个中间件,注意中间件的注册顺序是按序执行
    next();
  })
  // 获取用户列表信息的路由
  router.get('/user/list', (req, res) => {
    const userList = [
      {
        name: 'luffy',
        age: 24,
        gender: '男'
      },{
        name: 'lfy',
        age: 23,
        gender: '女'
      }
    ];
    res.json(userList);
  });
  // 所有的路由会加上“/interview”前缀
  app.use('/interview', router); //添加router中间件

  // express 自动帮我们创建一个server,封装的node底层http
  app.listen(3003, () => {
    console.log('node server is listening 3003');
  });

PS:这个文件就是我们监听后台端口,撰写接口的地方,通过express中的 router监听(即访问的接口),来触发不同的方法(即接口),然后返回数据
五、来测试一下前后端是不是通了

cd server
npm start
//后端express的运行
npm start
//前端运行

浏览器访问http://localhost:3003/api/user/list,页面上打印出刚刚server.js中的userList数组。前后端通了。
但是每次启动都得分两次分别启动前后端,很烦的。
修改package.json的scripts部分,首先安装一个concurrently的玩意儿,
npm install concurrently

"scripts": {
    "start-react": "react-scripts start",
    "build-react": "react-scripts build",
   + "start": "concurrently \"react-scripts start\" \"cd server && npm start\"",
   + "bulid": "concurrently \"react-app-rewired build\" \"cd server && npm build\"",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },

npm start就可以前后端同时启动了
六、完事具备,只欠数据~库。安装mongodb,官方教程。然后项目安装mongodb。npm install mongoose。(mongodb有很多可视化工具,本次使用的是studio 3T)
在根目录下新建db文件夹,文件夹目录如下
file
关于mongodb的基本概念
// 下面是关于mongoose的几个概念:
Schema: 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力
Model: 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对象
Entity: 由Model创建的实体,它的操作也会影响数据库
Schema、Model、Entity的关系请牢记,Schema生成Model,Model创造Entity。
Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。
1、config.js:

module.exports = {
    mongodb:'mongodb://127.0.0.1:27017/interview'
}
//127.0.0.1:27017其实就是我们的localhost,interview就是数据库名字,没设置用户名密码就不用写了

2、mongoose.js:

const mongoose = require('mongoose');
const config = require('./config');

module.exports = ()=>{
    mongoose.connect(config.mongodb);//链接数据库

    var db = mongoose.connection;
    db.on('error',console.log.bind('console','mongodb数据库连接错误!'));
    db.on('open',(callback)=>{
        console.log('mongodb数据库连接成功!');
    })
    //监听数据库连接和错误,使用回调抛出错误
    return db;
}

3、schemase.js

const mongoose = require('mongoose');
const schema = mongoose.Schema;

const Interview = new schema({
   question:String,
   code:String,
   word:String,
   type:String,
   time:Date
})
//此处映射一个数据库表结构,就是所谓的骨架
module.exports = Interview;

4、models.js

const mongoose = require('mongoose');
const Interview = require('../schemas/schemase');
//此处需要注意的是表明,所以mongoose.model()方法的第一个参数就是映射一个表名
//和数据库表要一致(需要少个s)mongodb会自己在映射的时候给表名添加一个s
//一个schema对应一个model对应一个数据库表
const Interviews = mongoose.model('interview',Interview);
module.exports = Interviews;

七、嘿嘿,真万事俱备,只欠接口
在server.js中的router.use()方法中写一个接口

router.get('/searchInterview', (req, res) => {
    let path = req.query.type;
    let Type = {'type':''};
    switch (path) {
      case 'cssinterview':Type.type = 'css';break;
      case 'jsinterview':Type.type = 'js';break;
      case 'vueinterview':Type.type = 'vue';break;
      case 'reactinterview':Type.type = 'react';break;
      case 'httpinterview':Type.type = 'http';break;
    }
    Interviews.find(Type,(err,data)=>{
      if(err){
        next(err);
        res.json(data);
      }else{
        res.json(data);
      }
    })
  });//按条件查询列表

前端随便找个地方写一个get方法

Get(
            '/interview/searchInterview',{type:pathName},
            (data)=>{
                console.log(data);
                this.setState({
                    tableData:data
                })
            },
            (err)=>{
                console.log(err)
            }
        )
哦吼,data即我们从数据库中查到的数据。

搞定,告辞~!
八、遇到的问题:
1、链接数据库之后查询,数据组为空,确认条件正确,schema正确,数据库连接正常,问题所在:model映射表时候表名错误,多写一个s,切记此处mongodb的坑,s、s、s。重要的事情说三遍
2、对于post、get请求参数获取方式,在server.js中有两行代码

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
这就是用来处理post,get所带参数的。
在接口router.get()或者router.post()的回调中有一个req的参数,这里面包括了好多东西(没参悟透)。req.body即post请求的参数,req.qurey即get请求的参数

九、关于express中的app.use()中间件
当一个请求发送到后台之后,后台会先接受到请求request,然后做出各种处理,然后在响应response,在接受到请求到响应这中间就可以做各种事情。中间件app.use()就是搞这个的,所谓的中间件就是一系列的函数,这一系列函数就可以对HTTP请求做一些列的处理。其中有next参数,next参数其实就是一个函数,表示下一个中间件函数,这样就可以依次去执行函数。express中维护一个中间件数组,这个数据就是一些列的中间件函数,当一个app.use(fun)使用过后,这个fun又会被扔回这个数据中,如果有执行next()则找这个函数的下一个函数,如果没有就终止了。

var express = require('express');
var app = express();
app.listen(3000, function () {
    console.log('listen 3000...');
});
function middlewareA(req, res, next) {
    console.log('middlewareA before next()');
    next();
    console.log('middlewareA after next()');
}
function middlewareB(req, res, next) {
    console.log('middlewareB before next()');
    next();
    console.log('middlewareB after next()');
}
function middlewareC(req, res, next) {
    console.log('middlewareC before next()');
    next();
    console.log('middlewareC after next()');
}
app.use(middlewareA);
app.use(middlewareB);
app.use(middlewareC);

输出:middlewareA before next()
middlewareB before next()
middlewareC before next()
middlewareA after next()
middlewareB after next()
middlewareC after next()

讨论数量: 2

写的不错哦~~

4年前

这是我见过最生动的分享整理了,读起来很生动!!!

4年前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!