thinkjs基础学习


前言

转载:https://thinkjs.org/zh-cn/doc/3.0/index.html

一、thinkjs介绍

ThinkJS 是一款面向未来开发的 Node.js 框架,整合了大量的项目最佳实践,让企业级开发变得更简单、高效。从 3.0 开始,框架底层基于 Koa 2.x 实现,兼容 Koa 的所有功能。

1、特性

  • 基于 Koa 2.x,兼容 middleware
  • 内核小巧,支持 Extend、Adapter 等插件方式
  • 性能优异,单元测试覆盖程度高
  • 内置自动编译、自动更新机制,方便快速开发
  • 使用更优雅的 async/await 处理异步问题,不再支持 */yield
  • 从 3.2 开始支持 TypeScript

2、架构

在这里插入图片描述

二、thinkjs安装

1、安装 ThinkJS 命令

$ npm install -g think-cli

安装完成后,系统中会有 thinkjs 命令(可以通过 thinkjs -V 查看 think-cli 的版本号,此版本号非 thinkjs 的版本号)。如果找不到这个命令,请确认环境变量是否正确。

如果是从 2.x 升级,需要将之前的命令删除,然后重新安装。

2、卸载旧版本命令

$ npm uninstall -g thinkjs

3、创建项目

执行 thinkjs new [project_name] 来创建项目,如:

$ thinkjs new demo;
$ cd demo;
$ npm install; 
$ npm start; 

执行完成后,控制台下会看到类似下面的日志:

[2017-06-25 15:21:35.408] [INFO] - Server running at http://127.0.0.1:8360
[2017-06-25 15:21:35.412] [INFO] - ThinkJS version: 3.0.0-beta1
[2017-06-25 15:21:35.413] [INFO] - Enviroment: development
[2017-06-25 15:21:35.413] [INFO] - Workers: 8

打开浏览器访问 http://127.0.0.1:8360/,如果是在远程机器上创建的项目,需要把 IP 换成对应的地址。

三、运行流程

Node.js 提供了 http 模块直接创建 HTTP 服务,用来响应用户的请求,比如 Node.js 官网提供的创建 HTTP 服务的例子:

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

ThinkJS 也是调用 http.createServer 的方式来创建服务的,所以整个运行流程包含了启动服务和响应用户请求二个部分。

1、系统服务启动

  • 执行 npm start 或者 node development.js
  • 实例化 ThinkJS 里的 Application 类,执行 run 方法。
  • 根据不同的环境(Master 进程、Worker 进程、命令行调用)处理不同的逻辑
    如果是 Master 进程
- 加载配置文件,生成 think.config 和 think.logger 对象。
- 加载文件 src/bootstrap/master.js 文件
- 如果配置文件监听服务,那么开始监听文件的变化,目录为 src/。
- 文件修改后,如果配置文件编译服务,那么会对文件进行编译,编译到 app/ 目录下。
- 根据配置 workers 来 fork 对应数目的 Worker。Worker 进程启动完成后,触发 appReady 事件。(可以通过 think.app.on("appReady") 来捕获)
- 如果文件发生了新的修改,那么会触发编译,然后杀掉所有的 Worker 进程并重新 fork。
  • 如果是 Worker 进程
1、加载配置文件,生成 think.config 和 think.logger 对象。
2、加载 Extend,为框架提供更多的功能,配置文件为 src/config/extend.js。
3、获取当前项目的模块列表,放在 think.app.modules 上,如果为单模块,那么值为空数组。
4、加载项目里的 controller 文件(src/controller/*.js),放在 think.app.controllers 对象上。
5、加载项目里的 logic 文件(src/logic/*.js),放在 think.app.logics 对象上。
6、加载项目里的 model 文件(src/model/*.js),放在 think.app.models 对象上。
7、加载项目里的 service 文件(src/service/*.js),放在 think.app.services 对象上。
8、加载路由配置文件 src/config/router.js,放在 think.app.routers 对象上。
9、加载校验配置文件 src/config/validator.js,放在 think.app.validators 对象上。
10、加载 middleware 配置文件 src/config/middleware.js,并通过 think.app.use 方法注册。
11、加载定时任务配置文件 src/config/crontab.js,并注册定时任务服务。
12、加载 src/bootstrap/worker.js 启动文件。
13、监听 process 里的 onUncaughtException 和 onUnhandledRejection 错误事件,并进行处理。可以在配置 src/config.js 自定义这二个错误的处理函数。
14、等待 think.beforeStartServer 注册的启动前处理函数执行,这里可以注册一些服务启动前的事务处理。
15、如果自定义了创建服务配置 createServer,那么执行这个函数 createServer(port, host, callback) 来创建服务。
16、如果没有自定义,则通过 think.app.listen 来启动服务。
17、服务启动完成时,触发 appReady 事件,其他地方可以通过 think.app.on("appReady") 监听。
18、创建的服务赋值给 think.app.server 对象。

服务启动后,会打印下面的日志:

[2017-07-02 13:36:40.646] [INFO] - Server running at http://127.0.0.1:8360
[2017-07-02 13:36:40.649] [INFO] - ThinkJS version: 3.0.0-beta1
[2017-07-02 13:36:40.649] [INFO] - Enviroment: development  #当前运行的环境
[2017-07-02 13:36:40.649] [INFO] - Workers: 8   #子进程数量

四、Context

Context 是 Koa 中处理用户请求中的一个对象,贯穿整个请求生命周期。一般在 middleware、controller、logic 中使用,简称为 ctx。

// 在 middleware 中使用 ctx 对象
module.exports = options => {
  // 调用时 ctx 会作为第一个参数传递进来
  return (ctx, next) => {
    ...
  }
}
// 在 controller 中使用 ctx 对象
module.exports = class extends think.Controller {
  indexAction() {
    // controller 中 ctx 作为类的属性存在,属性名为 ctx
    // controller 实例化时会自动把 ctx 传递进来
    const ip = this.ctx.ip;
  }
}

框架里继承了该对象,并通过 Extend 机制扩展了很多非常有用的属性和方法。

五、Controller / 控制器

MVC 模型中,控制器是用户请求的逻辑处理部分。比如:将用户相关的操作都放在 user.js 里,每一个操作就是里面一个 Action。

1、创建 Controller

项目中的 controller 需要继承 think.Controller 类,这样能使用一些内置的方法。当然项目中可以创建一些通用的基类,然后实际的 controller 都继承自这个基类。

项目创建时会自动创建了一个名为 base.js 的基类,其他 controller 继承该类即可。

你可以通过执行命令 thinkjs controller xxx [module]来添加controller,其中xxx为controller名称,而[module]为多模块项目中的项目名称,这时系统将自动完成controller与对应logic文件的创建,并且初始化其内容。

thinkjs controller user //新建user控制器
thinkjs controller auth api //在api模块下创建auth控制器

你也可以直接在对应目录中新建文件,如新建//src/controller/user.js来达到创建controller的目的

//src/controller/user.js

const Base = require('./base.js');
module.exports = class extends Base {
  indexAction(){
    this.body = 'hello world!';
  }
}

创建完成后,框架会监听文件变化然后重启服务。这时访问 http://127.0.0.1:8360/user/index 就可以看到输出的 hello word!

六、View / 视图

由于某些项目下并不需要 View 的功能,所以 3.0 里并没有直接内置 View 的功能,而是通过 Extend 和 Adapter 来实现的。

1、Extend 来支持 View

配置 src/config/extend.js,添加如下的配置,如果已经存在则不需要再添加:

const view = require('think-view');
module.exports = [
  view
]

通过添加视图的扩展,让项目有渲染模板文件的能力,视图扩展是通过模块think-view 实现的。

2、配置 View Adapter

src/config/adapter.js 中添加如下的配置,如果已经存在则不需要再添加:

const nunjucks = require('think-view-nunjucks');
const path = require('path');

// 视图的 adapter 名称为 view
exports.view = {
  type: 'nunjucks', // 这里指定默认的模板引擎是 nunjucks
  common: {
    viewPath: path.join(think.ROOT_PATH, 'view'), //模板文件的根目录
    sep: '_', //Controller 与 Action 之间的连接符
    extname: '.html' //模板文件扩展名
  },
  nunjucks: {
    handle: nunjucks,
    beforeRender: () => {}, // 模板渲染预处理
    options: { // 模板引擎额外的配置参数

    }
  }
}

这里用的模板引擎是 nunjucks,项目中可以根据需要修改。

3、具体使用

配置了 Extend 和 Adapter 后,就可以在 Controller 里使用了。如:

module.exports = class extends think.Controller {
  indexAction(){
    this.assign('title', 'thinkjs'); //给模板赋值
    return this.display(); //渲染模板
  }
}

4、模板预处理

有时候需要对模板进行预处理,比较常见的操作是给 nunjucks 引擎增加 Filter。这时候你就可以使用 beforeRender 方法。

const nunjucks = require('think-view-nunjucks');
const path = require('path');

exports.view = {
  type: 'nunjucks',
  common: {
    viewPath: path.join(think.ROOT_PATH, 'view'), //模板文件的根目录
    sep: '_', //Controller 与 Action 之间的连接符
    extname: '.html' //文件扩展名
  },
  nunjucks: {
    handle: nunjucks,
    beforeRender(env, nunjucks, config) {
      env.addFilter('utc', time => (new Date(time)).toUTCString());
    }
  }
}

七、关系数据库

在项目开发中,经常需要操作数据库(如:增删改查等功能),手工拼写 SQL 语句非常麻烦,同时还要注意 SQL 注入等安全问题。为此框架提供了模型功能,方便操作数据库。

1、扩展模型功能

框架默认没有提供模型的功能,需要加载对应的扩展才能支持,对应的模块为 think-model。修改扩展的配置文件 src/config/extend.js(多模块项目为 src/common/config/extend.js),添加如下的配置:

const model = require('think-model');

module.exports = [
  model(think.app) // 让框架支持模型的功能
]

添加模型的扩展后,会添加方法 think.Model、think.model、ctx.model、controller.model、service.model。

2、配置数据库

模型由于要支持多种数据库,所以配置文件的格式为 Adapter 的方式,文件路径为 src/config/adapter.js(多模块项目下为 src/common/config/adapter.js)。

const mysql = require('think-model-mysql');
exports.model = {
  type: 'mysql', // 默认使用的类型,调用时可以指定参数切换
  common: { // 通用配置
    logConnect: true, // 是否打印数据库连接信息
    logSql: true, // 是否打印 SQL 语句
    logger: msg => think.logger.info(msg) // 打印信息的 logger
  },
  mysql: { // mysql 配置
    handle: mysql
  },
  mysql2: { // 另一个 mysql 的配置
    handle: mysql
  },
  sqlite: {  // sqlite 配置

  },
  postgresql: { // postgresql 配置

  }
}

如果项目里要用到同一个类型的多个数据库配置,那么可以通过不同的 type 区分,如:mysqlmysql2,调用时可以指定参数切换。

const user1 = think.model('user'); // 使用默认的数据库配置,默认的 type 为 mysql,那么就是使用 mysql 的配置
const user2 = think.model('user', 'mysql2'); // 使用 mysql2 的配置
const user3 = think.model('user', 'sqlite'); // 使用 sqlite 的配置
const user4 = think.model('user', 'postgresql'); // 使用 postgresql 的配置

由于可以调用时指定使用哪个 type,理论上可以支持无限多的类型配置,项目中可以根据需要进行配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值