1.操作数据库中间件:egg-mongoose
egg框架后端代码操作mongodb数据库,需要借助中间件egg-mongoose,打开npm网站搜索,找到下载该中间件的官网,然后在项目中输入命令行下载:
npm i egg-mongoose
然后参考官网插件使用提示,将代码改造成MVC模式。
首先在config文件夹下,找到plugin.js文件,在exports对象里加入代码:
mongoose:{
enable: true,
package: 'egg-mongoose',
},
为了更详细展示,我把文件全部代码贴出来:
'use strict';
/** @type Egg.EggPlugin */
module.exports = {
// had enabled by egg
// static: {
// enable: true,
// }
mongoose:{
enable: true,
package: 'egg-mongoose',
},
nunjucks : {
enable: true,
package: 'egg-view-nunjucks',
}
};
和egg-mongoose官网介绍的代码略有不同,因为egg已经定义了exports对象,所以exports.mongoose的含义就是在其中定义一个mongoose对象。下面的nunjucks是后面要说的模板插件代码,对比两个代码可以发现,egg引入插件的方式大同小异。
同理,在config.default.js中插入如下代码:
config.mongoose = {
client: {
url: 'mongodb://127.0.0.1/eggDemo',
options: {},
// mongoose global plugins, expected a function or an array of function and options
// plugins: [createdPlugin, [updatedPlugin, pluginOptions]],
},
};
为什么和官网代码略有不同,上面已经介绍过。
2.M(model)
改造后app文件夹下的文件目录如图:
model文件夹下保存模型代码:
module.exports = app => {
const mongoose = app.mongoose;
const Schema = mongoose.Schema; //固定写法,调用egg-mongoose
//创建Schema对象,name、age、sex分别为数据库中对应的字段,type是字段的属性,其他属性参考官网。
const NewsSchema = new Schema({
name: { type: String },
age: { type: String },
sex:{type: String}
});
//.model()方法有三个属性,第一个属性‘News’指暴露给其他文件的模型名称,第二个为上面构造的实例名称
//第三个‘news’为数据库对应的表名。
return mongoose.model('News', NewsSchema,'news');
}
到此,一个最简单的包含三个字段的模型构造完成,复杂的模型无非也就是字段更多,字段本身的属性更多。
3.C(controller)
为什么先记录C,而不是V,是因为根据我浅薄的后端知识,将前后端代码整体可以分为四个元素:
- 数据库
- 后端代码Model部分
- 后端代码Controller部分
- 前端代码View部分
这四个部分依次连接,依次连接的意思就是不会出现View直接和Model出现交互的情况。
1)数据库中的字段对应着Model中定义的字段,至于怎么对应起来,不是我们使用框架的开发人员关注的。(其实如果只是想深入一步,可以参考mongoose创建连接的方式,十分简单,egg-mongoose创建连接的方式肯定是差不多的,不过作者水平有限,深入研究后端框架的源码,还属于高难度工作。)
2)Model中暴露出来的模型,交给Contorller中接口方法调用,Controller拿到模型的数据后,进行一系列操作,得到自己想要的数据。
3)Controller将符合自己需求的数据交给前端View部分,View再经过操作进行展示,前后端合作完毕。这是我理解的,前端请求接口后,后端所做操作的流程。前端请求如果带有参数,无非是在上述第二步中,Controller根据拿到的数据和前端传来的参数,进行操作,得到符合前端参数的数据。
根据这三步流程,可以看到,我们建好Model后,下一步就需要创建Controller获取数据,从而验证这两步有没有做错。
controller文件夹下创建news.js文件,其中代码如下:
'use strict';
const Controller = require('egg').Controller;
class NewsController extends Controller {
async list(){
const {ctx} = this;
// 通过模型获取数据,egg-mongoose操作mongodb数据库
// 调用模型,获取数据
const newsData = await ctx.model.News.find({}); //这里注意,这个News就是model中定义的模型变量,注意大小写
ctx.body={
error_code: 0,
msg: 'get success',
result:{
newsData
}
}
}
}
module.exports = NewsController;
在浏览器输入接口地址:http://127.0.0.1:8080/news/list
我根据习惯,把端口号改成了8080,egg框架默认的是7001。
得到效果如图:
在浏览器显示了我自己在数据库中手动创建的几条数据,说明M和C两层代码没有问题。
4.V(view)
本来想用art-template的,结果发现官网有个推荐的模板渲染,这种模板语法一般都差不多,主要是我懒,就不研究art-template了。
直接用egg框架推荐的模板egg-view-nunjucks:https://eggjs.org/zh-cn/core/view.html
配置插件的方法类似于上面的egg-mongoose,最简单的配置可以不用考虑配置多个目录。
在plugin.js中写:
nunjucks : {
enable: true,
package: 'egg-view-nunjucks',
}
在config.default.js中写入:
config.view = {
defaultViewEngine: 'nunjucks',
defaultExtension: '.nj',
mapping: {
'.nj': 'nunjucks',
},
}
- defaultViewEngine,建议配置,定义默认模板引擎。代码是通过后缀找到对应的模板引擎的,如果你前端页面写错了后缀,就会自动用这个引擎渲染。
- defaultExtension,建议配置,定义默认前端后缀。配置这个属性后,前端页面不用写后缀,会自动默认为.nj文件。
- mapping:必须配置,将该后缀名文件与模板引擎连接起来。“.nj”是根据模板引擎名称简写的,这个一般并不限制,可以随意取名,建议按照这个规范取名。
至此,模板引擎下载并配置完毕。
使用模板引擎渲染页面:
controller代码改造如下:
const newsData = await ctx.model.News.find({});
const ctxContent={
error_code: 0,
msg: 'get success',
result:[
...newsData
]
}
await ctx.render('news.nj', ctxContent);
newsData获取方式不变,定义一个变量ctxContent用来放我们要传递给前端的数据。其中result部分用es6解构的方式重新构造成一个数组。大家实际运行一下,将ctxContent打印出来,就知道为什么这么做了。
然后将ctxContent这个变量渲染到页面news.nj中,因为前面的配置,后缀可以省略,这里为了看着方便不犯迷糊。
在view文件夹下,创建news.nj文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>news</title>
</head>
<body>
<h1>news列表</h1>
姓名:{{result}}
</body>
</html>
效果如图:
至此MVC三层代码都走通了,地基已成。
感谢node.js,感谢egg.js,前端人终于有希望写一个自己的快速开发平台了。
正常情况下,webstorm或者其他编程软件应该是不认识.nj后缀的,所以此类型文件没有代码提示,没有自动编码功能,以webstorm为例,通过设置,让ide在操作.nj文件时和.html文件一样。
如图: