返回
前后端分离项目从入门到精通,完整详细版
前端
2024-01-16 06:46:02
创建一个 MERN 堆栈应用:后端、前端和部署
在本文中,我们将引导您逐步创建一个 MERN 堆栈应用程序,包括后端、前端和部署。本文适合初学者和希望加深对 MERN 堆栈理解的开发人员。
什么是 MERN 堆栈?
MERN 是一个流行的 JavaScript 开发堆栈,由以下组件组成:
- MongoDB: NoSQL 数据库
- Express.js: 用于创建 web 应用程序的后端框架
- React.js: 用于构建交互式前端的 JavaScript 库
- Node.js: JavaScript 运行时环境
安装和设置
后端
-
安装 Node.js 和 Express.js:
npm install -g nodejs npm install --save express
-
创建一个新的 Node.js 项目并安装 MongoDB 驱动程序:
mkdir day15-project cd day15-project npm init -y npm install --save mongoose
-
创建一个后端文件(例如 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);
前端
-
创建一个新的前端项目:
npx create-react-app day15-project-frontend cd day15-project-frontend npm start
-
创建一个前端文件(例如 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