You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4.6 KiB

ThinkJS 开发指南

框架简介

ThinkJS 是一个基于 Koa 2.x 的 Node.js MVC 框架,支持 ES6/7 特性,使用 async/await 处理异步。

目录结构说明

src/config/

  • config.js - 通用配置
  • config.production.js - 生产环境配置(会覆盖 config.js)
  • adapter.js - 适配器配置(数据库、缓存、会话等)
  • router.js - 自定义路由
  • middleware.js - 中间件配置
  • extend.js - 扩展配置

src/controller/

控制器目录,处理用户请求。

// src/controller/index.js
module.exports = class extends think.Controller {
  async indexAction() {
    // 获取参数
    const id = this.get('id');
    const data = this.post();
    
    // 调用 model
    const list = await this.model('article').select();
    
    // 渲染模板
    this.assign('list', list);
    return this.display();
  }
};

src/model/

数据模型目录,操作数据库。

// src/model/article.js
module.exports = class extends think.Model {
  // 获取文章列表
  async getList(columnId, page = 1, pageSize = 10) {
    return this.where({ column_id: columnId, status: 1 })
      .order('create_time DESC')
      .page(page, pageSize)
      .countSelect();
  }
};

src/logic/

逻辑层,用于参数校验。

// src/logic/article.js
module.exports = class extends think.Logic {
  indexAction() {
    this.allowMethods = 'get';
    this.rules = {
      id: { int: true, required: true }
    };
  }
};

常用 API

Controller

// 获取参数
this.get('name');           // GET 参数
this.post('name');          // POST 参数
this.param('name');         // GET + POST
this.file('upload');        // 上传文件

// 响应
this.success(data);         // JSON 成功响应
this.fail(errno, errmsg);   // JSON 失败响应
this.json(data);            // JSON 响应
this.redirect(url);         // 重定向

// 模板
this.assign('key', value);  // 赋值
this.display();             // 渲染模板

// Session
await this.session('user'); // 获取
await this.session('user', data); // 设置

// Cookie
this.cookie('name');        // 获取
this.cookie('name', value); // 设置

Model

const model = this.model('article');

// 查询
model.where({ id: 1 }).find();           // 单条
model.where({ status: 1 }).select();     // 多条
model.where({ status: 1 }).count();      // 计数
model.page(1, 10).countSelect();         // 分页

// 新增
model.add({ title: 'xxx', content: 'xxx' });
model.addMany([{...}, {...}]);

// 更新
model.where({ id: 1 }).update({ title: 'new' });

// 删除
model.where({ id: 1 }).delete();

// 链式调用
model.field('id, title')
  .where({ status: 1 })
  .order('id DESC')
  .limit(10)
  .select();

路由配置

// src/config/router.js
module.exports = [
  // [匹配规则, 'controller/action', method]
  ['/article/:id', 'article/detail', 'get'],
  ['/api/article', 'api/article', 'rest'],
  ['/admin/:controller/:action?', 'admin/:controller/:action'],
];

中间件

// src/config/middleware.js
module.exports = [
  {
    handle: 'meta',
    options: { logRequest: true }
  },
  {
    handle: 'resource',
    enable: true
  },
  'trace',
  'payload',
  'router',
  'logic',
  'controller'
];

数据库配置

// src/config/adapter.js
exports.model = {
  type: 'mysql',
  common: {
    logConnect: true,
    logSql: true,
    logger: msg => think.logger.info(msg)
  },
  mysql: {
    handle: mysql,
    database: 'pap_web',
    prefix: 'pap_',
    encoding: 'utf8mb4',
    host: '127.0.0.1',
    port: '3306',
    user: 'root',
    password: '',
    dateStrings: true
  }
};

视图模板 (Nunjucks)

<!-- view/index_index.html -->
{% extends "layout.html" %}

{% block content %}
<ul>
  {% for item in list %}
  <li>{{ item.title }}</li>
  {% endfor %}
</ul>

{% if pagination.totalPages > 1 %}
<div class="pagination">
  第 {{ pagination.currentPage }} / {{ pagination.totalPages }} 页
</div>
{% endif %}
{% endblock %}

常见问题

跨域处理

// src/config/middleware.js 添加
{
  handle: 'cors',
  options: {
    origin: '*',
    credentials: true
  }
}

文件上传

// controller
const file = this.file('image');
if (file) {
  const filepath = file.path;
  // 移动文件到目标目录
  think.fs.move(filepath, targetPath);
}

事务处理

const model = this.model('article');
await model.transaction(async () => {
  await model.add(data1);
  await this.model('log').add(data2);
});