核心原理:使用动态参数,使得传递任何资源都可以。通过客户端传递过来的动态参数,查找到客户端对应的模型文件。
问题:客户端传递过来的参数是小写复数形式(如categories、items),数据库模型类名是大写单数形式(如Category、Item)。
解决方法:采用中间件,把传递过来的动态参数名称转为数据库模型名称,并找到对应的数据库模型的类,挂载到请求对象上。
一. 安装所需包
# 用于处理单复数转换,单词的格式转换
npm i inflection
二. 项目结构
三. 核心代码
1. 入口文件 index.js :
const express=require("express")
const app=express()
app.use(express.json())
app.use(require('cors')())
app.use('/uploads',express.static(__dirname+'/uploads')) //静态文件托管
// 路由用module.exports导出一个函数,参数接收函数对象,在里面就可以用最外层的app
require('./routes/admin')(app)
require('./plugins/db')(app)
app.listen(3000,()=>{
console.log('http://localhost:3000')
})
2. 路由文件 /routes/admin/index.js :
// 通用CRUD接口 - 资源路由
// module.exports导出一个函数,参数接收函数对象,在里面就可以用最外层的app
module.exports=app=>{
const express=require('express')
//由于我们是在app.use()里定义的动态参数,又在router里用到动态参数,所以需要合并url参数
const router=express.Router({
mergeParams:true
})
// 数据库模型
// const Category=require('../../models/Category')
// 通用CRUD接口:动态参数,传递任何资源都可以。通过客户端传递过来的动态参数,查找到客户端对应的模型文件
// 新建xx列表
router.post('/',async(req,res)=>{
const model=await req.Model.create(req.body) //数据来源是客户端提交过来的数据
res.send(model) //创建完成后,发回给客户端
})
// 修改xx详情数据,通过id
router.put('/:id',async(req,res)=>{
const model=await req.Model.findByIdAndUpdate(req.params.id,req.body) //数据来源是客户端提交过来的数据
res.send(model) //创建完成后,发回给客户端
})
// 删除xx,通过id
router.delete('/:id',async(req,res)=>{
await req.Model.findByIdAndDelete(req.params.id)
res.send({
success:true
})
})
// 获取xx列表
router.get('/',async(req,res)=>{
const queryOptions = {}
let items=await req.Model.find().setOptions(queryOptions).limit(10)
if (req.Model.modelName === 'Category') {
//关联查询parent,使用populate取出关联字段的完整信息
//queryOptions.populate = 'parent'
items=await req.Model.find().populate('parent').limit(10)
}
// setOptions将后面的链式操作转化为对象的形式【不知道为什么操作无法生效???】
// const items=await req.Model.find().setOptions(queryOptions).limit(10) //xx列表的find,限制10条
res.send(items) //把数据发回给客户端
})
// 获取xx详情数据,通过id
router.get('/:id',async(req,res)=>{
const model=await req.Model.findById(req.params.id)
res.send(model) //把数据发回给客户端
})
// rest前缀代表restful风格的接口,防止通用CRUD接口和以后写的某个接口有冲突
// :resource为动态参数
// 中间件,用于把传递过来的动态参数名称转为数据库模型名称,并找到对应的数据库模型
app.use('/admin/api/rest/:resource',async(req,res,next)=>{
//转类名,将小写复数形式转成大写单数形式,例:categories转为Category
const modelName=require('inflection').classify(req.params.resource)
req.Model=require(`../../models/${modelName}`) // 得到数据库模型的类,挂载到请求对象上
next()
},router)
//上传文件
const multer=require('multer')
const upload=multer({dest:__dirname+'/../../uploads'}) //dest为目标地址
// single接收单个文件上传
app.post('/admin/api/upload',upload.single('file'),async(req,res)=>{
const file=req.file //multer把上传文件的数据挂载到req上了
file.url=`http://localhost:3000/uploads/${file.filename}`
res.send(file)
})
}
3. 数据库连接文件 /plugins/db.js :
// 数据库
module.exports=app=>{
const mongoose=require("mongoose")
mongoose.connect('mongodb://127.0.0.1:27017/node-vue-moba')
}
4. Mongodb数据库模型文件:
/models/Category.js :
const mongoose=require('mongoose')
// 定义模型的字段
const schema=new mongoose.Schema({
name:{type:String},
parent:{type:mongoose.SchemaTypes.ObjectId,ref:'Category'}, //数据类型是数据库中的ObjectId,ref指定要关联的模型
})
// 导出mongoose模型
module.exports=mongoose.model('Category',schema)
/models/Item.js :
const mongoose=require('mongoose')
// 定义模型的字段
const schema=new mongoose.Schema({
name:{type:String},
icon:{type:String},
})
// 导出mongoose模型
module.exports=mongoose.model('Item',schema)
参考资料:
你真的了解mongoose吗?_mb5ff590f157b0e的技术博客_51CTO博客你真的了解mongoose吗?,引言继上篇文章「Koa2+MongoDB+JWT实战--RestfulAPI最佳实践」后,收到许多小伙伴的反馈,表示自己对于mongoose不怎么了解,上手感觉有些难度,看官方文档又基本都是英文(宝宝心里苦,但宝宝不说)。为了让各位小伙伴快速上手,加深对于mongoose的了解,我特地结合之前的项目整理了一下关于mongoose的一些基础知识,这些对于实战都是很有用的。相信看了这篇文章,https://blog.51cto.com/u_15077541/2608049[第一章 + 第二章] NodeJs + VueJs (Express + ElementUI) 全栈开发王者荣耀手机端官网和管理后台_哔哩哔哩_bilibili免费不易,淘宝同名店铺《全栈之巅》求关注QQ2群:839167184,微信加小姐姐732500779拉群Git 源码: https://github.com/wxs77577/node-vue-moba,代码都在各个分支里,持续更新中,欢迎 star;编辑器 vscode,主题 material theme,字体mononoki;请先安装 nodejs 10+ ,mongodb server,no
https://www.bilibili.com/video/BV1A4411Y7fi?p=14&spm_id_from=333.1007.top_right_bar_window_history.content.clickvscode实用快捷键查找和替换_Angela-的博客-CSDN博客_vscode全局替换快捷键vscode是一款功能十分强大的编辑器,且带有许多插件,利用插件可以让开发速度提升几倍甚至几十倍。vscode快捷键:查找:单文件查找:ctrl + F替换:单文件内替换一处:crtl + shift + 1单文件内替换全部:ctrl + alt + enter也可以用鼠标点击替换,如图查找文件夹下所有文件中是否包含某个关键字:ctrl + shift + F替换全局查找检索到...
https://blog.csdn.net/weixin_44135807/article/details/102513935