返回

前后端分离项目从入门到精通,完整详细版

前端

创建一个 MERN 堆栈应用:后端、前端和部署

在本文中,我们将引导您逐步创建一个 MERN 堆栈应用程序,包括后端、前端和部署。本文适合初学者和希望加深对 MERN 堆栈理解的开发人员。

什么是 MERN 堆栈?

MERN 是一个流行的 JavaScript 开发堆栈,由以下组件组成:

  • MongoDB: NoSQL 数据库
  • Express.js: 用于创建 web 应用程序的后端框架
  • React.js: 用于构建交互式前端的 JavaScript 库
  • Node.js: JavaScript 运行时环境

安装和设置

后端

  1. 安装 Node.js 和 Express.js:

    npm install -g nodejs
    npm install --save express
    
  2. 创建一个新的 Node.js 项目并安装 MongoDB 驱动程序:

    mkdir day15-project
    cd day15-project
    npm init -y
    npm install --save mongoose
    
  3. 创建一个后端文件(例如 app.js):

    // app.js
    const express = require('express');
    const mongoose = require('mongoose');
    
    const app = express();
    
    mongoose.connect('mongodb://localhost/day15-project');
    
    // 定义模式
    const KindSchema = new mongoose.Schema({
      kind_name: String
    });
    
    const AnimalSchema = new mongoose.Schema({
      ani_name: String,
      weight: Number,
      height: Number,
      kind: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Kind'
      }
    });
    
    // 创建模型
    const Kind = mongoose.model('Kind', KindSchema);
    const Animal = mongoose.model('Animal', AnimalSchema);
    
    // 路由
    app.get('/kinds', async (req, res) => {
      const kinds = await Kind.find();
      res.send(kinds);
    });
    
    app.post('/kinds', async (req, res) => {
      const kind = new Kind(req.body);
      await kind.save();
      res.send(kind);
    });
    
    app.put('/kinds/:id', async (req, res) => {
      const kind = await Kind.findByIdAndUpdate(req.params.id, req.body);
      res.send(kind);
    });
    
    app.delete('/kinds/:id', async (req, res) => {
      await Kind.findByIdAndDelete(req.params.id);
      res.send({ message: 'Kind deleted' });
    });
    
    app.get('/animals', async (req, res) => {
      const animals = await Animal.find().populate('kind');
      res.send(animals);
    });
    
    app.post('/animals', async (req, res) => {
      const animal = new Animal(req.body);
      await animal.save();
      res.send(animal);
    });
    
    app.put('/animals/:id', async (req, res) => {
      const animal = await Animal.findByIdAndUpdate(req.params.id, req.body);
      res.send(animal);
    });
    
    app.delete('/animals/:id', async (req, res) => {
      await Animal.findByIdAndDelete(req.params.id);
      res.send({ message: 'Animal deleted' });
    });
    
    app.listen(3000);
    

前端

  1. 创建一个新的前端项目:

    npx create-react-app day15-project-frontend
    cd day15-project-frontend
    npm start
    
  2. 创建一个前端文件(例如 App.js):

    // App.js
    import React, { useState, useEffect } from 'react';
    import axios from 'axios';
    
    const App = () => {
      const [kinds, setKinds] = useState([]);
      const [animals, setAnimals] = useState([]);
    
      useEffect(() => {
        axios.get('/kinds')
          .then(res => setKinds(res.data))
          .catch(err => console.log(err));
      }, []);
    
      useEffect(() => {
        axios.get('/animals')
          .then(res => setAnimals(res.data))
          .catch(err => console.log(err));
      }, []);
    
      const createKind = (e) => {
        e.preventDefault();
        const kindName = e.target.kindName.value;
        axios.post('/kinds', { kind_name: kindName })
          .then(res => setKinds([...kinds, res.data]))
          .catch(err => console.log(err));
      };
    
      const updateKind = (e) => {
        e.preventDefault();
        const kindId = e.target.kindId.value;
        const kindName = e.target.kindName.value;
        axios.put(`/kinds/${kindId}`, { kind_name: kindName })
          .then(res => setKinds(kinds.map(kind => kind._id === res.data._id ? res.data : kind)))
          .catch(err => console.log(err));
      };
    
      const deleteKind = (e) => {
        e.preventDefault();
        const kindId = e.target.kindId.value;
        axios.delete(`/kinds/${kindId}`)
          .then(() => setKinds(kinds.filter(kind => kind._id !== kindId)))
          .catch(err => console.log(err));
      };
    
      const createAnimal = (e) => {
        e.preventDefault();
        const animalName = e.target.animalName.value;
        const animalWeight = e.target.animalWeight.value;
        const animalHeight = e.target.animalHeight.value;
        const animalKind = e.target.animalKind.value;
        axios.post('/animals', { ani_name: animalName, weight: animalWeight, height: animalHeight, kind: animalKind })
          .then(res => setAnimals([...animals, res.data]))
          .catch(err => console.log(err));
      };
    
      const updateAnimal = (e) => {
        e.preventDefault();
        const animalId = e.target.animalId.value;
        const animalName = e.target.animalName.value;
        const animalWeight = e.target.animalWeight.value;
        const animalHeight = e.target.animalHeight.value;
        const animalKind = e.target.animalKind.value;
        axios.put(`/animals/${animalId}`, { ani_name: animalName, weight: animalWeight, height: animalHeight, kind: animalKind })
          .then(res => setAnimals(animals.map(animal => animal._id === res.data._id ? res.data : animal)))
          .catch(err => console.log(err));
      };
    
      const deleteAnimal = (e) => {
        e.preventDefault();
        const animalId = e.target.animalId.value;
        axios.delete(`/animals/${animalId}`)
          .then(() => setAnimals(animals.filter(animal => animal._id !== animalId)))
          .catch(err => console.log(err));
      };
    
      return (
        <div>
          <h1>Kinds</h1>
          <ul>
            {kinds.map(kind => (
              <li key={kind._id}>
                {kind.kind_name}
                <button onClick={updateKind}>Update</button>
                <button onClick={deleteKind}>Delete</button>
              </li>
            ))}
          </ul>
          <form onSubmit={createKind}>
            <input type="text" name="kindName" placeholder="Kind name" />
            <button type="submit">Create</button>
          </form>
    
          <h1>Animals</h1>
          <ul>
            {animals.map(animal => (
              <li key={animal._id}>
                {animal.ani_name} ({animal.weight}kg, {animal.height}cm) - {animal.kind.kind_name}
                <button onClick={updateAnimal}>Update</button>
                <button onClick={deleteAnimal}>Delete</button>
              </li>
            ))}
          </ul>
          <form onSubmit={createAnimal}>
            <input type="text" name="animalName" placeholder="Animal name" />
            <input type="number" name="animalWeight" placeholder="Animal weight (kg)" />
            <input type="number" name="animalHeight" placeholder="Animal height (cm)" />
            <select name="animalKind">
              {kinds.map(kind => (
                <option value={kind._id}>{kind.kind_name}</option>
              ))}
            </select>
            <button type="submit">Create