一、前端部分:
技术栈:react,react-bootstrap
思路:
- 在使用npm init建立起来的node项目中创建文件夹建立前端,这是前后端不分离,前后端分离也差不多就这样
- 将react初始项目src文件夹中文件大部分删除,留下app.js,index.js,index.css,reportWebVitals
- 下载react-bootstrap,并引入文件bootstrap.min.css
- 下载react-router-dom,在入口文件App.js中引入路由,使得<Router>置于app.js的return中最高
import React from "react"; import { BrowserRouter as Router,Route } from "react-router-dom"; import Header from "./components/Header"; import Footer from "./components/Footer"; import { Container } from "react-bootstrap"; import HomeScreen from "./screens/HomeScreen"; import ProductScreen from "./screens/ProductScreen"; function App() { return ( <Router> <Header /> <main className="py-3"> <Container> <Route path='/' component={HomeScreen} exact /> <Route path='/products/:id' component={ProductScreen} exact /> </Container> </main> <Footer /> </Router> ); } export default App;
- 建立components文件夹放组件,建立screens文件夹放页面
- 对于一个网站的设计,头部header和底部footer组件必不可少,而且这两部分不会随着页面的跳转而消失,上面app.js中的代码将route放在了main标签中,也就是这个意思
- 对于在商城中的每一件商品,我们在点击相应的按钮后跳转的实际都是ProductScreen这一个页面,改变的只是页面的商品数据,所以我们在前端项目中需要下载axios,并在页面的代码中引入axios发起get请求,请求数据代码如下:
-
const [product, setProduct] = useState([]); useEffect(() => { const fetchProduct = async () => { const { data } = await axios.get(`/api/products/${match.params.id}`); setProduct(data); }; fetchProduct(); }, []);
- 为了快速搭建前端,我们往往会引用风格库,如font-awesome
二、后端部分:
技术栈:express,mongoDB
思路:
- 后端需要连接数据库,我们这里使用的是mongoDB,下载mongoDB之后,我们需要配置db
-
const mongoose = require('mongoose'); const connectDB=async()=>{ try{ const conn =await mongoose.connect(process.env.MONGO_URL, {useUnifiedTopology:true, useNewUrlParser:true, } ) console.log(`MongoDB Connected: ${conn.connection.host}`); }catch(error){ console.log(`Error: ${error.message}`); process.exit(1); } } module.exports=connectDB
- 配置完db之后我们在server.js中就可以引入db.js,从而连接数据库
- 服务器的搭建就不细说了,在我之前的blog讲过node搭建服务器
- 在目前项目的第一部分,我们没有大量数据去支撑这个数据库,所以我们使用在前端搭建阶段使用的例子数据,也就是编的数据,我们需要把这个数据放到常见的mongoDB数据库中去,在这个情况下,我们需要创建我们自己的数据模板,就是说你自己需要什么样模式的数据,你将数据的格式写在这个model文件中
-
const mongoose = require('mongoose'); const reviewSchema=mongoose.Schema({ name:{ type:String, required:true, }, rating:{ type:Number, required:true, }, comment:{ type:String, required:true, }, }) const productSchema=mongoose.Schema({ user:{ type:mongoose.Schema.Types.ObjectId, required:true, ref:'User' }, image:{ type:String, required:true, unique:true }, brand:{ type:String, required:true, }, reviews:[reviewSchema], category:{ type:String, required:true, }, price:{ type:Number, required:true }, description:{ type:String, required:true, }, rating:{ type:Number, required:true, default:0 }, numReviews:{ type:Number, required:true, default:0 }, countInStock:{ type:Number, required:true, default:0 } },{ timestamps:true }) const Product=mongoose.model('Product',productSchema); module.exports=Product
- 上面代码是product的model代码,有了这个之后,我们需要创建seeder.js来将已有的样子数据以模板的方式放入数据库或者销毁数据
-
const mongoose = require('mongoose'); const users = require('./data/users.js'); const dotenv = require('dotenv'); const products = require('./data/products.js'); const User = require('./models/userModel.js'); const Product = require('./models/productModel.js'); const Order =require("./models/orderMode") const connectDB = require('./config/db.js'); dotenv.config(); connectDB(); const importData = async () => { try { await Order.deleteMany(); await Product.deleteMany(); await User.deleteMany(); const createdUsers = await User.insertMany(users); const adminUser = createdUsers[0]._id const sampleProducts = products.map(product => { return { ...product, user: adminUser } }) await Product.insertMany(sampleProducts) console.log('Data Imported!'); process.exit(); } catch (error) { console.error(`${error}`); process.exit(1); } } const destroyData = async () => { try { await Order.deleteMany(); await Product.deleteMany(); await User.deleteMany(); console.log('Data Destroyed'); process.exit(); } catch (error) { console.error(`${error}`); process.exit(1); } } if(process.argv[2] === '-d') { destroyData(); } else { importData(); }