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

本文共 6105 字,大约阅读时间需要 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部署相关可以

转载地址:http://amqtl.baihongyu.com/

你可能感兴趣的文章
JSTL、EL、ONGL、Struts标签的区别与使用
查看>>
Xamarin提示Build-tools版本过老
查看>>
Android库分析工具(崩溃反编译)
查看>>
otl翻译(11) -- OTL的迭代器
查看>>
POJ 2184 Cow Exhibition 01背包
查看>>
51术语详解
查看>>
[linux]scp指令
查看>>
深入理解CSS定位中的堆叠z-index
查看>>
自从升级到macOS后,整个人都不好了
查看>>
linux网卡掉包或挂掉解决办法
查看>>
border-style 属性
查看>>
如何用 Uber JVM Profiler 等可视化工具监控 Spark 应用程序?
查看>>
拒绝旧国标劣质排插,新国标插线板首选品胜
查看>>
新疆国省干线总里程突破2.9万公里
查看>>
国产智轨电车开进“冰城”接受严寒测试 表现良好
查看>>
缓解“钱紧” 央行本周公开市场净投放创两年新高
查看>>
21岁大专学历,刚培训完前端,不造假简历,能找到工作吗?
查看>>
国内首部区块链行业纪录片开播
查看>>
List集合就这么简单【源码剖析】
查看>>
Spring Cloud (十四):Spring Cloud 开源软件都有哪些?
查看>>