博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue+thinkJs博客网站(二)之thinkJs的使用
阅读量:5734 次
发布时间:2019-06-18

本文共 6179 字,大约阅读时间需要 20 分钟。

简介

这个个人博客网站最初制作的目的就是练习使用thinkJs,这一篇就主要讲一下thinkJs的一些特性和注意事项。涉及到了文件上传,thinkJs的插件机制,model层建立以及CURD的编写方式等。本项目github地址。目thinkJs端主要参考了知乎上大神Ischo的文章,链接。

thinkJs model层写法

这里主要讲两个部分,一是表对应的js文件,二是CRUD写法。项目表结构比较简单,一共八个表,包含多对一,一对多,多对多关系。主要的几个表,都对应着model文件夹下的js文件,表关系也在这个js里维护。这里我们以model/content.js为例讲一哈:

module.exports = class extends think.Model {    // 模型关联    get relation() {        return {            category: {                type: think.Model.BELONG_TO,                model: "meta",                key: "category_id",                fKey: "id",                field: "id,name,slug,description,count"            },            tag: {                type: think.Model.MANY_TO_MANY,                model: "meta",                rModel: "relationship",                rfKey: "meta_id",                key: "id",                fKey: "content_id",                field: "id,name,slug,description,count"            },            comment: {                type: think.Model.HAS_MANY,                key: "id",                fKey: "content_id",                where: "status=99",                order: "create_time desc"            },            user: {                type: think.Model.BELONG_TO,                model: "user",                key: "user_id",                fKey: "id",                field: "id,username,email,qq,github,weibo,zhihu"            }        };    }    // 添加文章    async insert(data) {        const tags = data.tag;        data = this.parseContent(data);        delete data.tag;        const id = await this.add(data);        const relation = [];        tags.forEach(val => {            relation.push({                content_id: id,                meta_id: val            });        });        think.model("relationship").addMany(relation);        // 更新文章数量        this.updateCount(data.category_id, tags);        return id;    }}复制代码

这里代码没有截全,完整代码看github。

我们看到这个对象分为两部分,一个是get relation写的表映射关系。可以看到content表与meta表存在一对一关系(type: think.Model.BELONG_TO),这里key:category_id是content表里的字段,即外键,fkey:id是对应的meta表里的字段。查询时,会封装层user.category对象,对象属性就是field 定义的id,name,slug,description,count。content 与user也存在多对多关系(type: think.Model.MANY_TO_MANY),rfModel是多对多关系下,对应的关联关系模型名,默认值为二个模型名的组合,rfKey是多对多关系下,关系表对应的 key。

另一个是Model里的方法,相当于自定义的model方法,比如这里定义的insert,就可以在controller里通过this.model('content').insert()调用。

thinkJS的CRUD操作,不是直接写sql,而是在sql基础上封装一层,通过调用model的方法来操作。think.Model 基类提供了丰富的方法进行 CRUD 操作,具体如下:

查询数据模型提供了多种方法来查询数据,如:find 查询单条数据select 查询多条数据count 查询总条数countSelect 分页查询数据max 查询字段的最大值avg 查询字段的平均值min 查询字段的最小值sum 对字段值进行求和getField 查询指定字段的值同时模型支持通过下面的方法指定 SQL 语句中的特定条件,如:where 指定 SQL 语句中的 where 条件limit / page 指定 SQL 语句中的 limitfield / fieldReverse 指定 SQL 语句中的 fieldorder 指定 SQL 语句中的 ordergroup 指定 SQL 语句中的 groupjoin 指定 SQL 语句中的 joinunion 指定 SQL 语句中的 unionhaving 指定 SQL 语句中的 havingcache 设置查询缓存添加数据模型提供了下列的方法来添加数据:add 添加单条数据thenAdd where 条件不存在时添加addMany 添加多条数据selectAdd 添加子查询的结果数据更新数据模型提供了下列的方法来更新数据:update 更新单条数据updateMany 更新多条数据thenUpdate 条件式更新increment 字段增加值decrement 字段减少值删除数据模型提供了下列的方法来删除数据:delete 删除数据手动执行 SQL 语句有时候模型包装的方法不能满足所有的情况,这时候需要手工指定 SQL 语句,可以通过下面的方法进行:query 手写 SQL 语句查询execute 手写 SQL 语句执行复制代码

比如我们要查询content表数据,在Controller里通过thin.model('content').where(param).select()来查询。

thinkJs的Model层与之前用过的java的数据层框架hibernate比较相似,都是基于面向对象的思想对sql进行封装,表与Model(实体类),通过model方法进行CRUD操作,特别省sql。

插件机制的实现

参考的博主实现的插件机制还是很好用的,这里我就拿了过来。插件机制可以说是自定义的钩子函数。首先在src新建service文件夹,新建js文件(以cache.js为例)

module.exports = class extends think.Service {    static registerHook() {        return {            content: ["contentCreate", "contentUpdate", "contentDelete"]        };    }    /**     * 更新内容缓存     * @param  {[type]} data [description]     * @return {[type]}      [description]     */    content(data) {        think.cache("recent_content", null);    }};复制代码

registerHook里content对应的数组表示钩子函数的调用名,具体调用的是下面的content方法。在controller里这么调用

await this.hook("contentUpdate", data);复制代码

钩子函数的注册这里放到了worker进程里,thinkJs运行流程具体的可以看看官网 。work.js代码如下:

think.beforeStartServer(async () => {    const hooks = [];    for (const Service of Object.values(think.app.services)) {        const isHookService = think.isFunction(Service.registerHook);        if (!isHookService) {            continue;        }        const service = new Service();        const serviceHooks = Service.registerHook();        for (const hookFuncName in serviceHooks) {            if (!think.isFunction(service[hookFuncName])) {                continue;            }            let funcForHooks = serviceHooks[hookFuncName];            if (think.isString(funcForHooks)) {                funcForHooks = [funcForHooks];            }            if (!think.isArray(funcForHooks)) {                continue;            }            for (const hookName of funcForHooks) {                if (!hooks[hookName]) {                    hooks[hookName] = [];                }                hooks[hookName].push({ service, method: hookFuncName });            }        }    }    think.config("hooks", hooks);});复制代码

这里将service里定义的method遍历取出,按一定格式保存并存放到数组,最后放到think.config里面,项目启动后这些过程就已经执行了。

think.Controller本身没有hook方法,这里需要在extend里面加上controller.js,代码如下:

module.exports = {    /**     * 执行hook     * @param  {[type]}    name [description]     * @param  {...[type]} args [description]     * @return {[type]}         [description]     */    async hook(name, ...args) {        const { hooks } = think.config();        const hookFuncs = hooks[name];        if (!think.isArray(hookFuncs)) {            return;        }        for (const { service, method } of hookFuncs) {            await service[method](...args);        }    }};复制代码

这样自定义钩子函数就实现了,一些通用的后置方法就可以直接共用一个了。

路由

thinkJs路由写在config/router.js里,具体代码如下:

module.exports = [  // RESTFUL  [/\/api\/(\w+)(?:\/(.*))?/, 'api/:1?id=:2', 'rest'],  [/\/font\/(\w+)\/(\w+)/, 'fontend/:1/:2'],  ['/:category/:slug', 'content/detail'],  ['/:category/:slug/comment', 'content/comment']];复制代码

里面的数组的第一个元素是匹配url的表达式,第二个元素是分配的资源,如果是采用RESTFUL规范定义的接口,第三个元素要写作'rest'。本项目的后台接口基本都是采用RESTFUL规范,具体路由的详细讲解可以。

部署

项目线上部署采用PM2管理node进程,部署时把src,view,www,pm2.json,production.js放到服务器上。安装好pm2后运行

pm2 start pm2.json复制代码

注意pm2.json里需要修改cwd为服务器上你项目的目录。本项目前后端是一个服务,不存在所以没有用nginx代理。thinkJs部署相关可以。

转载于:https://juejin.im/post/5c78ad62e51d4572c95840c9

你可能感兴趣的文章
学习Kubernetes 和容器技术体系的最佳方法
查看>>
IBM开源JVM实现OpenJ9,并提交Eclipse基金会托管
查看>>
IBM开源的Open Liberty项目简介
查看>>
深入JVM彻底剖析ygc越来越慢的原因(下)
查看>>
Jquery与Bootstrap实现后台管理页面增删改查功能
查看>>
在惨遭勒索病毒攻击之后,微软呼吁重新制定“数字日内瓦公约”
查看>>
RSocket:又一个REST的挑战者
查看>>
杠上Spark、Flink?Kafka为何转型流数据平台
查看>>
“为什么中国没有Apache基金会这样的组织?”
查看>>
C#的未来:方法契约
查看>>
PWA即将推向所有Chrome平台
查看>>
使用Prometheus监控Cloudflare的全球网络
查看>>
.NET Core 3.0中的数据库驱动框架System.Data
查看>>
Python数据可视化2018:数据可视化库为什么这么多?
查看>>
Micronaut教程:如何使用基于JVM的框架构建微服务
查看>>
Analytics Zoo:在Apache Spark上实现分布式Tensorflow和BigDL管道的统一分析和AI平台
查看>>
全新Docker Hub发布:提供查找、存储和共享容器镜像单一体验
查看>>
据Progress调查:2018年,70%的客户在使用NoSQL
查看>>
腾讯信鸽海量移动推送服务是如何构建的
查看>>
数组的reduce方法
查看>>