上一章总结了项目中常用的CRUD操作和常见问题,但是由于一个个写不同内容的接口过于冗余,其功能大体上是一致的,所以需要将接口进行改造,转变为通用的CRUD接口。这样当前端请求不同种类的接口时可以根据模型的类型来进行转化与匹配,大大降低代码的重复度。
1 基本思路
-
修改路径成为动态资源
-
封装接口并且加上动态参数
-
通过传来的动态参数查找到对应的模型文件,并且修改原来固定的模型名为动态获取的(需要转换格式)
-
前端接口修改成和后台接口统一的格式
2 具体实现
-
修改路由接口路径
/**修改前**/ router.post('/categories(某具体路径)',async(req,res)=>{...}) /**修改后**/ router.post('/',async(req,res)=>{...}) //无参数 router.put('/:id',async(req,res)=>{...}) //有参数,带id
-
封装接口为/admin/api/rest/,并且加上动态参数,第四个参数resource动态参数
app.use('/admin/api/rest/:resource',resourceMiddleware(),router)
-
通过传来的动态参数查找到对应的模型文件,并且修改原来固定的模型名为动态获取的(需要转换格式)
const modelName=require('inflection').classify(req.params.resource) 大写单数 req.Model=require(`../models/${modelName}`)
并且替换所有的模型名为req.Model
const model=await req.Model.create(req.body) const model=await req.Model.findByIdAndUpdate(req.params.id,req.body) await req.Model.findByIdAndDelete(req.params.id,req.body) const model=await req.Model.findById(req.params.id) ...
-
前端接口修改成和后台接口统一的格式
const res= await this.$http.get('rest/categories')
-
将获取动态参数并转化为模型名的代码转化为中间件引入
新建middleware/resource.js,封装中间件resourceMiddleware(),并挂载到app上
module.exports=options=>{ return async(req,res,next)=>{ const modelName=require('inflection').classify(req.params.resource) req.Model=require(`../models/${modelName}`) //给请求对象挂载一个属性Model next() } }
3 其他细节问题
-
动态参数和模型命名规范
路径名(如:categories,小写开头且为负数) =》 模型名(如:Category,大写开头且为单数)
categories =》 Category
-
动态参数转化为模型名 需要安装 inflection用于处理单复数转换
npm i inflection
-
Category的特殊性,有些需要查父类的资源需要做如下的修改
const queryOptions={}
if(req.Model.modelName==='Category'){
queryOptions.populate='parent'
}
const items=await req.Model.find().setOptions(queryOptions).limit(100)
res.send(items)