从0到1开发一个小程序 – Part 2

从0到1开发一个小程序 – Part 2

前言

在上一篇文章中,我们介绍了 Egg.js 的基本使用方法。在本文中,我们将继续深入了解 Egg.js 的核心概念,包括 Controller、Service、Model 以及路由,并编写一个简单的增删改查的 demo,来展示这些概念的实际应用。

Egg.js 核心概念-Controller

Controller 是 Egg.js 的 MVC 架构中的控制器,它用于处理用户的请求并返回响应结果。在 Egg.js 中,一个 Controller 对应一个 URL 路由,用户发送请求时,Controller 将根据 URL 路由来执行对应的方法,并返回响应结果。

在 Egg.js 的 Controller 中,可以通过 ctx 对象获取请求和响应的相关信息。ctx.request 对象用于获取请求相关信息,ctx.response 对象用于设置响应相关信息。

下面是一个简单的 Controller 示例:

// app/controller/home.js
const Controller = require('egg').Controller;

class HomeController extends Controller {
  async index() {
    const { ctx } = this;
    ctx.body = 'Hello, world!';
  }
}

module.exports = HomeController;

在上面的示例中,我们定义了一个 HomeController,它继承自 Egg.js 的 Controller 类。我们在 HomeController 中定义了一个 index 方法,当用户访问 / 路径时,它将被执行,并返回一个字符串 Hello, world!。

Egg.js 核心概念-Service

Egg.js 中的 Service 是一个非常重要的概念,用于处理业务逻辑,如读取数据库、调用 API 等。与 Controller 不同的是,Service 中的方法可以被多个 Controller 中的 action 共享调用,实现了业务逻辑的复用。

Service 的使用

使用 Service 首先需要在应用目录下的 app/service 目录中创建相应的服务文件,例如:

// app/service/user.js
const Service = require('egg').Service;

class UserService extends Service {
  async find(id) {
    const user = await this.ctx.db.query('select * from users where id = ?', id);
    return user;
  }
}

module.exports = UserService;

上面的代码创建了一个 UserService,其中 find 方法从数据库中查询用户信息并返回。通过在 Service 中封装相关的业务逻辑,我们可以将其暴露给其他的 Controller 使用。

在 Controller 中使用 Service,需要通过 this.ctx.service 调用。例如:

javascriptCopy code
// app/controller/user.js
class UserController extends Controller {
  async index() {
    const ctx = this.ctx;
    const id = ctx.query.id;
    const user = await ctx.service.user.find(id);
    ctx.body = user;
  }
}

上面的代码中,Controller 中的 index 方法通过 ctx.service.user.find(id) 调用 UserService 中的 find 方法查询用户信息并返回。

Service 的生命周期

在 Egg.js 中,每个 Service 都是通过 Egg.js 的机制来创建的,因此 Service 也有自己的生命周期。下面是 Service 的生命周期方法:

  • constructor(ctx):构造函数,接收一个 ctx 参数,用于获取请求上下文。
  • async didLoad():Service 文件加载完成后的回调函数。
  • async willReady():所有的插件都已启动完毕时,调用此函数。
  • async didReady():应用启动完成后的回调函数。
  • async serverDidReady():Server 启动完成后的回调函数。
  • async beforeClose():应用关闭前的回调函数。

例如:

class UserService extends Service {
  constructor(ctx) {
    super(ctx);
    console.log('Service constructor');
  }

  async didLoad() {
    console.log('Service didLoad');
  }

  async willReady() {
    console.log('Service willReady');
  }

  async didReady() {
    console.log('Service didReady');
  }

  async serverDidReady() {
    console.log('Service serverDidReady');
  }

  async beforeClose() {
    console.log('Service beforeClose');
  }

  async find(id) {
    const user = await this.ctx.db.query('select * from users where id = ?', id);
    return user;
  }
}

Egg.js 核心概念-Model

在 Egg.js 中,使用 Model 去操作数据库是非常常见的。Egg.js 默认使用了 Sequelize,但也可以通过插件来支持 MongoDB、MySQL、Redis 等其他数据库。

在本篇文章中,我们将使用 MongoDB 作为我们的数据库。在 Egg.js 中,使用 MongoDB 最常见的插件是 mongoose。接下来我们将一步步来演示如何使用 mongoose 插件。

首先,我们需要在项目中安装 mongoose,可以使用 npm 进行安装:

cssCopy code
npm install --save egg-mongoose mongoose

安装完成之后,在 config/plugin.js 中添加配置:

javascriptCopy code
// config/plugin.js
exports.mongoose = {
  enable: true,
  package: 'egg-mongoose',
};

接下来在 config/config.default.js 中添加 MongoDB 的配置:

javascriptCopy code
// config/config.default.js
exports.mongoose = {
  client: {
    url: 'mongodb://localhost:27017/yourdb',
    options: {},
  },
};

这里的 url 是你 MongoDB 的地址,options 是连接的选项。

接下来,我们就可以在应用中使用 mongoose 进行数据操作了。例如,我们创建一个 user 的 model:

javascriptCopy code
// app/model/user.js
module.exports = app => {
  const mongoose = app.mongoose;
  const UserSchema = new mongoose.Schema({
    username: { type: String, unique: true },
    password: { type: String },
    email: { type: String, unique: true },
    createdAt: { type: Date, default: Date.now },
    updatedAt: { type: Date, default: Date.now },
  });

  return mongoose.model('User', UserSchema);
};

在这里我们使用 mongoose 的 Schema 来定义用户的数据结构,包括用户名、密码、邮箱、创建时间和更新时间。然后使用 mongoose.model 方法创建一个名为 User 的 model。

接下来,我们就可以在我们的 Service 中使用该 Model 来进行数据操作了。例如,我们实现一个 User 的 Service,用来处理用户相关的业务逻辑:

javascriptCopy code
// app/service/user.js
const Service = require('egg').Service;

class UserService extends Service {
  async createUser(username, password, email) {
    const user = new this.ctx.model.User({
      username,
      password,
      email,
    });

    return user.save();
  }

  async getUserById(id) {
    return this.ctx.model.User.findById(id);
  }

  async updateUserById(id, data) {
    return this.ctx.model.User.findByIdAndUpdate(id, data);
  }

  async deleteUserById(id) {
    return this.ctx.model.User.findByIdAndRemove(id);
  }
}

module.exports = UserService;

在这里,我们使用 this.ctx.model.User 来获取到我们刚刚创建的 User Model。然后,我们实现了创建用户、获取用户、更新用户、删除用户等方法。这些方法会在 Controller 中被调用,用来完成具体的业务逻辑。

Egg.js 核心概念-路由

路由是egg.js中负责处理客户端请求的一个核心概念,它定义了URL与处理请求的方法之间的映射关系。在egg.js中,我们可以通过编写路由来将请求分发给相应的Controller方法进行处理。

以下是一个简单的路由示例:

javascriptCopy code
// app/router.js

module.exports = app => {
  const { router, controller } = app;

  router.get('/', controller.home.index);
};

这个示例中,我们首先导入了egg.js中的router和controller模块,然后定义了一个GET请求的路由。这个路由将根路径'/'映射到了controller中的index方法。

我们可以看到,路由的处理过程非常简单。首先我们通过router.get方法定义了一个GET请求的路由,然后指定了路径为'/',并将请求分发给了controller中的index方法。在这个方法中,我们可以编写任何我们想要的业务逻辑,并通过调用ctx.body方法将处理结果返回给客户端。

除了GET请求外,egg.js还支持多种HTTP请求方式,例如POST、PUT、DELETE等。我们可以通过类似的方法来定义不同请求方式的路由,例如:

javascriptCopy code
router.post('/user', controller.user.create);
router.put('/user/:id', controller.user.update);
router.delete('/user/:id', controller.user.delete);

以上示例中,我们定义了一个POST请求的路由,用于创建用户。我们还定义了PUT和DELETE请求的路由,用于更新和删除用户信息。这些路由都将请求分发给了controller中相应的方法进行处理。

总的来说,egg.js中的路由非常简单明了,通过编写路由,我们可以轻松地将请求分发给相应的Controller方法进行处理,实现我们想要的业务逻辑。

结语

在本文中,我们介绍了egg.js的核心概念,包括Controller、Service、Model和路由。通过理解这些概念,我们可以更好地进行egg.js的开发。在接下来的文章中,我们将会使用这些概念来实现小程序后台服务的系统管理模块,让我们一起期待下一篇文章的到来吧。

原文链接:https://juejin.cn/post/7221081978996555813 作者:Desever

(0)
上一篇 2023年4月13日 上午10:52
下一篇 2023年4月13日 上午11:02

相关推荐

发表回复

登录后才能评论