手记

【金秋打卡】第10天 创建用户模型

课程名称:web前端架构师

课程章节:第15周 第八章 用户系统的设计与实现

主讲老师:张轩

课程内容: 创建用户模型

创建用户模型

引入 egg-mongoose

将我们之前写的 mongoose插件 替换为 egg-mongoose

npm i egg-mongoose

在 plugin.ts 文件中启用 egg-mongoose 插件

const plugin: EggPlugin = {
  mongoose: {
    enable: true,
    package: 'egg-mongoose',
  },
};

在 config.default.ts 文件中配置mongoose,配置与我们之前写的一样,不过 egg-mongoose 支持传入 options


  config.mongoose = {
    url: 'mongodb://localhost:27017',
    // 可以将 url 中的用户名、密码、数据库名等放到 options 上
    options: {
      user: 'root',
      pass: '*******',
      dbName: 'lego',
    },
  };

创建用户模型

import { Application } from 'egg';
export interface User{
  username: string
  password: string
  email?: string
  nickname?: string
  pickture?: string
  phoneNumber?: string
  createdAt: Date
  updatedAt: Date
}
export default (app: Application) => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;
  const UserSchema = new Schema<User>({
    username: String,
    password: String,
    email: String,
    nickname: String,
    phoneNumber: String,
  }, { timestamps: true });
  return mongoose.model<User>('User', UserSchema);
};

这里需要注意的是 Schema 第二个参数传 timestamps 可以帮我们自动创建 craeteAt 和 updateAt的值

创建用户

首先完成第一个接口,创建用户

在 serve 中编写操作数据库的代码, 在 service 目录下创建 user.ts

import { Service } from 'egg';
import { User } from '../model/User';

export default class UserService extends Service {

  public async createByEmail(payload: User) {
    const { ctx } = this;
    const { username, password } = payload;
    const user: Partial<User> = {
      username,
      password,
      email: username,
    };
    return ctx.app.model.User.create(user);
  }
  public async findById(id: string) {
    return this.ctx.app.model.User.findById(id);
  }
}

编写 controller, 调用service ,并把数据返回给用户

import { Controller } from 'egg';

export default class UserController extends Controller {
  public async createByEmail() {
    const { ctx, service } = this;
    const res = await service.user.createByEmail(ctx.request.body);
    ctx.body = {
      res,
      code: 0
    };
  }
}

最后配置路由

import { Application } from 'egg';

export default (app: Application) => {
  const { controller, router } = app;
  router.post('/signup', controller.user.createByEmail);
};

这样代码创建用户代码就完成了

存在问题

由于 egg-mongoose 使用的 mongoose 版本是5.x的,很长时间没有更新了。它对 ts 的支持并不友好,我上面我们写代码时,很多时候时没有提示的信息,这样使用很不舒服。例如

export default (app: Application) => {
  const mongoose = app.mongoose;
  const Schema = mongoose.Schema;
  const UserSchema = new Schema<User>({
  // 这里编写没有提示
    username: String,
    password: String,
    email: String,
    nickname: String,
    phoneNumber: String,
  }, { timestamps: true });
  return mongoose.model<User>('User', UserSchema);
};

改进 Model

我们在写 servie 下调用调用 model 操作数据库时,也是没有提示的。例如下面代码

export default class UserService extends Service {

  public async createByEmail(payload: User) {
    const { ctx } = this;
    const { username, password } = payload;
    const user: Partial<User> = {
      username,
      password,
      email: username,
    };
    // 这里不会提示, ctx.app.model.User 是 Model<any, {}, {}>
    return ctx.app.model.User.create(user);
  }
  public async findById(id: string) {
   // 这里不会提示, ctx.app.model.User 是 Model<any, {}, {}>
   // this.ctx.app.model.User.findById(id) 这个结果也没有字段提示 
    return this.ctx.app.model.User.findById(id);
  }

我们可以 在 typings/index.d.ts 文件中声明 User 类型

import 'egg';
import { User } from '../app/model/user'
declare module 'egg' {
  interface MongooseModels{
    User: Model<User>
  }
}

然后到代码里验证

 public async findById(id: string) {
 // this.ctx.app.model.  时就会出现提示 User
    const res = await this.ctx.app.model.User.findById(id);
    if (res) {
    // res. 时,就会出现 res 上的一些属性,比如username password 等
      console.log(res.username);
    }
    return res;
 }

上面代码虽然实现了有提示信息,但是需要我们每次都要编写代码,不是很好

我们每次保存代码都会自动生成 typings 下的代码,除了index.d.ts ,其他代码都会自动声明 对应文件夹下的 .d.ts 文件,我们可以查看 typings/app/model/index.d.ts 文件


import 'egg';
// 导入我们 model 目录下的所有文件
import ExportUser from '../../../app/model/User';

declare module 'egg' {
  interface IModel {
  // key 时 User,即我们的文件名首字母大写,值就是我们 export default导出的返回值
  // 每次保存都会自动生成  所有。[文件名]:[export default导出的返回值]
    User: ReturnType<typeof ExportUser>;
  }
}

每次保存文件,它都会自动生成,导入我们的代码,生成类型声明文件 ,IModel 这个接口会导入我们 model 下的所有文件,所以我们可以在 index.d.ts 中利用 IModel 来实现我们想要的,每次修改完代码,不需要手动来修改 index.d.ts

import 'egg';
import { User } from '../app/model/user'
declare module 'egg' {
  interface MongooseModels extends IModel{
  }
}

0人推荐
随时随地看视频
慕课网APP