eggjs全栈开发规范,前端开发项目实例

  • 启用

  • 使用方法

  • 模板渲染(选用nunjucks)

    • 安装
  • 启用与配置

  • 使用方法

  • 静态文件

  • Git规范

    • 分支类型
  • 分支命名

  • 开发流程

  • 提交格式

  • 接口自测

    • 软件
  • 操作规范

  • RESTful API规范

    • 请求协议
  • 请求方法

  • 状态码

    • 成功状态码
  • 错误状态码

  • 服务器错误状态码

  • 自定义状态码

  • 版本号

  • URL规范

  • 请求体格式

  • 返回体格式

  • 过滤、分页与排序

    • 过滤
  • 排序

  • 分页

  • 请求格式

编码规范

===================================================================

编码格式与语法


项目默认编码格式统一为UTF-8格式,语法采用ES6+语法

代码注释


注释符号后要有一个空格

函数/方法注释

函数/方法注释放置于函数/方法的上方,主要描述函数/方法功能以及参数类型,参数和返回值说明

/**

  • 功能

  • @param {参数类型} 参数名 参数说明

  • @return {返回值类型} 返回值 返回值说明

*/

单行注释

对代码做简要说明

// 功能简要说明

代码分段及缩进


每段代码应放在一个代码块中。块内的代码都应该统一地缩进一个单位。

使用空格作为缩进

使用2个空格作为一个缩进单位。

代码块符号

代码块的开始符号要放在行尾,不可单独一行;代码块结束符号要单独一行。

function demo() { // 代码块开始符号

// …} // 代码块结束符号

空白行分隔


不同功能或多个代码块之间,使用空白行分隔

/**

  • 方法1

*/function demo1() {

}

/**

  • 方法2

*/function demo1() {

… // 代码块1

… // 代码块2}

命名规则


全部使用英文单词

文件命名

  • 控制器,模型,服务的文件名使用小写名词。

  • 中间件使用下划线分割命名。

  • 使用中间件使用将下划线命名改为首字母小写的驼峰命名。

  • 控制器,服务的类名为首字母大写的文件名+Controller。

变量与常量命名

尽量使用const代替let

若变量需要改变才使用let

固定常量为全大写,其余使用首字母小写的驼峰命名法

函数/方法命名

使用首字母小写的驼峰命名

引号


一般情况使用单引号,若字符串拼接,使用"``“和”${}"

分号


不用分号

项目规范

===================================================================

库的安装和项目的初始化全部使用npm

项目生成


egg-init 项目名 --type=simple

npm install

安装第三方库


$ npm i --save 库名

项目运行


项目开发运行

$ npm run dev

项目部署运行

$ npm run start

项目docker运行

向package.json中的scripts键添加一个值

“scripts”: {

“docker”: “egg-sequelize db:migrate && egg-scripts start”,

…}

2.4 项目目录

├── app.js

├── app

│ ├── router.js

│ ├── controller

│ ├── extend

│ ├── middleware

│ ├── service

│ ├── public

│ ├── view

│ ├── router

│ ├── io (自建socket.io目录)

│ │ ├── middleware

│ │ └── controller

│ └── model (自建Sequelize目录)

├── config

│ ├── plugin.js

│ ├── config.default.js

│ └── config.prod.js

├── migrations(自建Sequelize目录)

├── logs

└── test

└── app

├── middleware

└── controller

以上目录约定如下:

1.app/router.js 用于配置URL路由规则。

2.app/controller/ 用于解析用户输入,处理后返回响应结果。

3.app/extend/ 用于框架内部对象的拓展(request,response,context,application)和工具类(helper)的编写。

4.app/middleware/ 用于编写中间件。

5.app/service/ 用于编写业务逻辑,如数据库操作的封装,api请求的封装等。

6.app/public/ 用于放置静态文件。

7.app/view/ 用于放置模板文件(可能不需要)。

8.app/model/ 用于放置数据模型(若使用Sequelize)。

9.app/router/ 用户放置分离的路由

10.migrations/ 用与放置数据库迁移的文件。

11.logs/ 日志存放目录。

12.test/ 测试文件目录。

13.app.js 用于自定义启动时的初始化工作。

项目相关文件说明


所有代码均在’use strict’严格模式下开发

extend

包含四个对象对应的文件,以及一个helper工具类

1.代码格式

‘use strict’

module.exports = {

/**

  • 方法说明

  • @param {参数类型} 参数名 参数说明

  • @return {返回值类型} 返回值名 返回值说明

*/

方法名(参数) {

// 处理逻辑

return 返回值

},

get 属性名() {

// 属性相关逻辑

return 属性

},

set 属性名(值) {

this.set(键, 值)

},}

2.application.js

对应Application对象

访问方式:

  • ctx.app

  • Controller, Helper, Service中都能使用this.app访问,例如this.app.config访问配置对象

  • Middleware中使用 ctx.app 访问

  • 将app对象作为函数的第一个参数注入 module.exports = app => {}

3.context.js

对应context对象

访问方式:

  • middleware中this就是 ctx

  • controller中使用this.ctx访问

  • helper,service中使用this.ctx访问

4.request.js

对应request.js对象

访问方式:

  • ctx.request

相关方法:

  • ctx.request.body 获取客户端请求的body参数

  • ctx.request.headers 获取客户端请求的header

  • ctx.request.query/ctx.query 获取URL内的参数

  • ctx.request.params 获取路由配置的参数

5.response.js

对应response.js对象

访问方式:

  • ctx.response

相关方法:

  • ctx.response.body/ctx.body 响应给客户端的body参数

6.helper.js

工具类,将请求成功和请求失败返回封装的函数以及错误码的封装写到里面

访问方式:

  • ctx.helper

  • 若要在非请求状态下,调用ctx,比如service中使用ctx.helper,则使用以下方法

const { app } = this.ctx;const ctx = app.createAnonymousContext();

ctx.helper.ROOTURL //此变量即可调用

封装状态码,将其解释写在helper里,方便调用

module.exports = {

errorCode: {

200: ‘请求成功。客户端向服务器请求数据,服务器返回相关数据’,

201: ‘资源创建成功。客户端向服务器提供数据,服务器创建资源’,

202: ‘请求被接收。但处理尚未完成’,

204: ‘客户端告知服务器删除一个资源,服务器移除它’,

206: ‘请求成功。但是只有部分回应’,

400: ‘请求无效。数据不正确,请重试’,

401: ‘请求没有权限。缺少API token,无效或者超时’,

403: ‘用户得到授权,但是访问是被禁止的。’,

404: ‘发出的请求针对的是不存在的记录,服务器没有进行操作。’,

406: ‘请求失败。请求头部不一致,请重试’,

410: ‘请求的资源被永久删除,且不会再得到的。’,

422: ‘请求失败。请验证参数’,

500: ‘服务器发生错误,请检查服务器。’,

502: ‘网关错误。’,

503: ‘服务不可用,服务器暂时过载或维护。’,

504: ‘网关超时。’,

}}

在Controller中响应客户端时,使用

this.ctx.body = {

code: 400,

message: this.ctx.helper.errorCode[400],

data:{

error:‘err’

}}

封装请求成功的方法

module.exports= {

success: ({ ctx, code=200, res=null }) => {

ctx.status = 200

ctx.body = {

code: code,

message: ctx.helper.errorCode[code],

data: res

}

}}

封装请求失败的方法

module.exports = {

fail: ({ ctx, code=500, res=null }) => {

ctx.status = 200

ctx.body = {

code: code,

message: ctx.helper.errorCode[code],

data: {

error: res

}

}

}}

请求封装使用例子

ctx.helper.success({ ctx, code:200, res:‘success’ })

ctx.helper.fail({ ctx, code:500, res:‘fail’ })

配置文件

1.plugin.js

引入第三方插件

代码格式:

exports.插件名 = {

enable: true,

package: ‘库名’}

例如:

exports.jwt = {

enable: true,

package: ‘egg-jwt’}

2.config.{{env}}.js

访问方式:

  • this.app.config

  • this.config

代码格式:

‘use strict’

module.exports = appInfo => {

const config = exports = {}

// 全局变量

config.变量名=‘’

// 插件名

config.插件名= {

// 相关配置

}}

例如:

‘use strict’

module.exports = appInfo => {

const config = exports = {}

// redis 配置

config.redis = {

client: {

port: process.env.RS_PORT || 6379,

host: process.env.RS_HOST || ‘0.0.0.0’,

password: process.env.RS_PASSWORD || ‘’,

db: 0,

}

}}

  • 默认配置放置在config.default.js,所有环境都会加载

  • 本地环境使用config.local.js

  • 开发环境使用config.prod.js

Middleware

中间件。对于一些错误拦截,请求处理,需要使用中间件完成。

配置方法:

  • 文件名命名使用下划线分割,在config.{{env}}.js文件中的middleware中配置,使用的是驼峰方式配置

例如:中间件文件名为demo-middleware 在config.{{env}}.js中的配置

config.middleware = [‘demoMiddleware’]

  • 在路由中配置,同样使用中间件时名称使用驼峰方式

例如:

module.exports = app => {

const demo = app.middleware.demoMiddleware()

app.router.get(‘/url’, demo, app.controller.demo)}

代码格式:

‘use strict’

module.exports = () => {

return async function 方法名(ctx, next) {

await next()

// 相关逻辑

}}

例如:

‘use strict’

module.exports = () => {

return async function notFoundHandler(ctx, next) {

await next()

if (ctx.status === 404 && !ctx.body) {

ctx.body = { error: ‘Not Found’ }

}

}}

处理错误信息的中间件

‘use strict’

module.exports = (option, app) => {

return async function(ctx, next) {

try {

await next()

} catch (err) {

app.emit(‘error’, err, this)

const status = err.status || 500

// 生产环境下不将错误内容返回给客户端

const error = status === 500 && app.config.env === ‘prod’

? ‘服务器错误,请联系管理员!’
err.message

ctx.helper.fail({ctx, code:status, res:error})

if(status === 422) {

ctx.helper.fail({ctx, code:status, res:err.errors})

}

}

}}

Service

保持Controller中逻辑简洁,以及业务逻辑的独立性,抽象出的Service可以被多个Controller调用。比如封装数据库操作的方法,API请求封装,第三方服务调用等。

访问方式:

  • this.service

Service支持多级目录,访问的时候可以通过目录名级联访问

  • app/service/biz/user.js => ctx.service.biz.user

  • app/service/sync_user.js => ctx.service.syncUser

  • app/service/HackerNews.js => ctx.service.hackerNews

代码格式(类的方式):

  • 类名使用首字母大写的驼峰命名法

  • 获取ctx,app,service,config,logger等对象使用const {对象} = this的方式获取

‘use strict’

const Service = require(‘egg’).Service

class 类名 extends Service {

/**

  • 方法说明

  • @param {参数类型} 参数名 参数说明

  • @return {返回值类型} 返回值名 返回值说明

*/

async 方法名(参数名) {

// 方法逻辑

return 返回值

}}

方法例子如下:

/**

  • 添加礼物

  • @param {string} livecode 编号

  • @return {int} giftnum 礼物数量

*/async addGift(livecode) {

const { app } = this

const giftnum = await this.ctx.model.query(UPDATE live SET gift=gift+1 WHERE livecode='${livecode}')

return giftnum}

Controller

三种功能,处理restful接口用户传来的参数;模板渲染;请求代理

访问方式:

  • 可以支持多级目录,访问的时候可以通过目录名级联访问

例如:

  • app.controller.post.create() // 代码放在 app/controller/post.js

  • app.controller.sub.post.create() // 代码放在 app/controller/sub/post.js

代码格式(类的方式):

  • 命名使用文件名首字母大写+Controller

  • 获取ctx,app,service,config,logger等对象使用const {对象} = this的方式获取

‘use strict’

const Controller = require(‘egg’).Controller

class 首字母大写的文件名+Controller extends Controller {

async 方法名() {

// 相关逻辑

ctx.body = {

// 返回给restful api接口的请求者

}

}}

例如:

‘use strict’

const Controller = require(‘egg’).Controller

class HomeController extends Controller {

async index() {

const {ctx} = this

if(ctx.isAuthenticated) {

ctx.body = {

user: ctx.user

}

} else {

ctx.body = {

user: ‘fail’

}

}

}}

module.exports = HomeController

router.js路由文件

描述请求的URL与controller建立的联系。将各个路由分离开来,分别放入router文件夹,并在router.js中引入

代码格式:

‘use strict’

/**

  • @param {Egg.Application} app - egg application

*/

module.exports = app => {

const { router, controller } = app

router.操作(‘/URL路径’, 中间件1, …中间件n, controller.文件名.方法) }

例如:

‘use strict’

/**

  • @param {Egg.Application} app - egg application

*/

module.exports = app => {

const { router, controller } = app

const roleCheck = app.middleware.roleCheck()

router.get(‘/user’, app.jwt, roleCheck, controller.user.getAllUser)}

带参路由,两种形式,以及获取参数的方式:

1.使用形如/uri/:id的uri,在Controller中使用ctx.request.params获取 例如:

// router.js

router.get(‘/user/:id’, controller.user.info)

// controllerconst { ctx } = thisconst { id } = ctx.request.params

1.使用形如/uri?id=1&age=1的uri,在Controller中使用ctx.query获取 例如:

// router.js

router.get(‘/user?id=1&age=1’, controller.user.msg)

// controllerconst { ctx } = thisconst { id, age } = ctx.query

安全配置


开发的时候关闭csrf,防止无法请求接口

// csrf关闭

config.security = {

csrf: {

enable: false

}}

Sequelize


安装

$ npm i -s egg-sequelize mysql2

启用与配置

在plugin.js中启用Sequlize

exports.sequelize = {

enable: true,

package: ‘egg-sequelize’}

在config.{{env}}.js中配置数据库连接.账户相关的信息,开发状态下将信息填入config.local.js;部署环境下,将信息填入config.prod.js

config.sequelize = {

dialect: ‘mysql’,

database: process.env.DB_DATABASE || ‘数据库名’,

host: process.env.DB_HOST || ‘IP地址’,

port: process.env.DB_PORT || ‘数据库端口号’,

username: process.env.DB_USER || ‘数据库用户名’,

password: process.env.DB_PASSWORD || ‘数据库密码’,

timezone: ‘+08:00’}

在package.json中配置数据库迁移命令

“scripts”: {

“migrate:new”: “egg-sequelize migration:create”,

“migrate:up”: “egg-sequelize db:migrate”,

“migrate:down”: “egg-sequelize db:migrate:undo”}

开发过程中配置自动同步数据库(仅开发模式),在app.js中写入

module.exports = app => {

if(app.config.env === ‘local’) {

app.beforeStart(async () => {

await app.model.sync({force:true})

})

}}

model数据模型开发

文档参考:https://demopark.github.io/sequelize-docs-Zh-CN/models-definition.html

  • 文件名为表名

  • 在文件前面引入需要的字段类型const {类型} = Sequelize

代码格式:

‘use strict’

module.exports = app => {

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

JavaScript 和 ES6

在这个过程你会发现,有很多 JS 知识点你并不能更好的理解为什么这么设计,以及这样设计的好处是什么,这就逼着让你去学习这单个知识点的来龙去脉,去哪学?第一,书籍,我知道你不喜欢看,我最近通过刷大厂面试题整理了一份前端核心知识笔记,比较书籍更精简,一句废话都没有,这份笔记也让我通过跳槽从8k涨成20k。

JavaScript部分截图

库密码’,

timezone: ‘+08:00’}

在package.json中配置数据库迁移命令

“scripts”: {

“migrate:new”: “egg-sequelize migration:create”,

“migrate:up”: “egg-sequelize db:migrate”,

“migrate:down”: “egg-sequelize db:migrate:undo”}

开发过程中配置自动同步数据库(仅开发模式),在app.js中写入

module.exports = app => {

if(app.config.env === ‘local’) {

app.beforeStart(async () => {

await app.model.sync({force:true})

})

}}

model数据模型开发

文档参考:https://demopark.github.io/sequelize-docs-Zh-CN/models-definition.html

  • 文件名为表名

  • 在文件前面引入需要的字段类型const {类型} = Sequelize

代码格式:

‘use strict’

module.exports = app => {

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-XpE56nMQ-1710593077778)]
[外链图片转存中…(img-1zfI00Ri-1710593077779)]
[外链图片转存中…(img-zXtqY0qn-1710593077779)]
[外链图片转存中…(img-zZ86zsoL-1710593077779)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
[外链图片转存中…(img-n5t8XVM3-1710593077780)]

JavaScript 和 ES6

在这个过程你会发现,有很多 JS 知识点你并不能更好的理解为什么这么设计,以及这样设计的好处是什么,这就逼着让你去学习这单个知识点的来龙去脉,去哪学?第一,书籍,我知道你不喜欢看,我最近通过刷大厂面试题整理了一份前端核心知识笔记,比较书籍更精简,一句废话都没有,这份笔记也让我通过跳槽从8k涨成20k。

JavaScript部分截图

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值