摘要:插件機制可以說是自定義的鉤子函數(shù)。首先在新建文件夾,新建文件以為例更新內(nèi)容緩存里對應(yīng)的數(shù)組表示鉤子函數(shù)的調(diào)用名,具體調(diào)用的是下面的方法。
一.簡介
這個個人博客網(wǎng)站最初制作的目的就是練習(xí)使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。
項目thinkJs端主要參考了知乎上大佬Ischo的文章,鏈接在這。
二.thinkJs model層寫法
這里主要講兩個部分,一是表對應(yīng)的js文件,二是CRUD寫法。項目表結(jié)構(gòu)比較簡單,一共八個表,包含多對一,一對多,多對多關(guān)系。主要的幾個表,都對應(yīng)著model文件夾下的js文件,表關(guān)系也在這個js里維護。這里我們以model/content.js為例講一哈:
module.exports = class extends think.Model { // 模型關(guān)聯(lián) 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); // 更新文章數(shù)量 this.updateCount(data.category_id, tags); return id; } }
這里代碼沒有截全,完整代碼看github。
我們看到這個對象分為兩部分,一個是get relation寫的表映射關(guān)系。可以看到content表與meta表存在一對一關(guān)系(type: think.Model.BELONG_TO),這里key:category_id是content表里的字段,即外鍵,fkey:id是對應(yīng)的meta表里的字段。查詢時,會封裝層user.category對象,對象屬性就是field 定義的id,name,slug,description,count。content 與user也存在多對多關(guān)系(type: think.Model.MANY_TO_MANY),rfModel是多對多關(guān)系下,對應(yīng)的關(guān)聯(lián)關(guān)系模型名,默認值為二個模型名的組合,rfKey是多對多關(guān)系下,關(guān)系表對應(yīng)的 key。
另一個是Model里的方法,相當(dāng)于自定義的model方法,比如這里定義的insert,就可以在controller里通過this.model("content").insert()調(diào)用。
thinkJS的CRUD操作,不是直接寫sql,而是在sql基礎(chǔ)上封裝一層,通過調(diào)用model的方法來操作。think.Model?基類提供了豐富的方法進行 CRUD 操作,具體如下:
查詢數(shù)據(jù) 模型提供了多種方法來查詢數(shù)據(jù),如: find 查詢單條數(shù)據(jù) select 查詢多條數(shù)據(jù) count 查詢總條數(shù) countSelect 分頁查詢數(shù)據(jù) max 查詢字段的最大值 avg 查詢字段的平均值 min 查詢字段的最小值 sum 對字段值進行求和 getField 查詢指定字段的值 同時模型支持通過下面的方法指定 SQL 語句中的特定條件,如: where 指定 SQL 語句中的 where 條件 limit / page 指定 SQL 語句中的 limit field / fieldReverse 指定 SQL 語句中的 field order 指定 SQL 語句中的 order group 指定 SQL 語句中的 group join 指定 SQL 語句中的 join union 指定 SQL 語句中的 union having 指定 SQL 語句中的 having cache 設(shè)置查詢緩存 添加數(shù)據(jù) 模型提供了下列的方法來添加數(shù)據(jù): add 添加單條數(shù)據(jù) thenAdd where 條件不存在時添加 addMany 添加多條數(shù)據(jù) selectAdd 添加子查詢的結(jié)果數(shù)據(jù) 更新數(shù)據(jù) 模型提供了下列的方法來更新數(shù)據(jù): update 更新單條數(shù)據(jù) updateMany 更新多條數(shù)據(jù) thenUpdate 條件式更新 increment 字段增加值 decrement 字段減少值 刪除數(shù)據(jù) 模型提供了下列的方法來刪除數(shù)據(jù): delete 刪除數(shù)據(jù) 手動執(zhí)行 SQL 語句 有時候模型包裝的方法不能滿足所有的情況,這時候需要手工指定 SQL 語句,可以通過下面的方法進行: query 手寫 SQL 語句查詢 execute 手寫 SQL 語句執(zhí)行
比如我們要查詢content表數(shù)據(jù),在Controller里通過thin.model("content").where(param).select()來查詢。
thinkJs的Model層與之前用過的java的數(shù)據(jù)層框架hibernate比較相似,都是基于面向?qū)ο蟮乃枷雽ql進行封裝,表與Model(實體類),通過model方法進行CRUD操作,特別省sql。
三.插件機制的實現(xiàn)
參考的博主實現(xiàn)的插件機制還是很好用的,這里我就拿了過來。插件機制可以說是自定義的鉤子函數(shù)。首先在src新建service文件夾,新建js文件(以cache.js為例)
module.exports = class extends think.Service { static registerHook() { return { content: ["contentCreate", "contentUpdate", "contentDelete"] }; } /** * 更新內(nèi)容緩存 * @param {[type]} data [description] * @return {[type]} [description] */ content(data) { think.cache("recent_content", null); } };
registerHook里content對應(yīng)的數(shù)組表示鉤子函數(shù)的調(diào)用名,具體調(diào)用的是下面的content方法。在controller里這么調(diào)用
await this.hook("contentUpdate", data);
鉤子函數(shù)的注冊這里放到了worker進程里,thinkJs運行流程具體的可以看看官網(wǎng)在這里
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遍歷取出,按一定格式保存并存放到數(shù)組,最后放到think.config里面,項目啟動后這些過程就已經(jīng)執(zhí)行了。
think.Controller本身沒有hook方法,這里需要在extend里面加上controller.js,代碼如下:
module.exports = { /** * 執(zhí)行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); } } };
這樣自定義鉤子函數(shù)就實現(xiàn)了,一些通用的后置方法就可以直接共用一個了。
四.路由
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"] ];
里面的數(shù)組的第一個元素是匹配url的表達式,第二個元素是分配的資源,如果是采用RESTFUL規(guī)范定義的接口,第三個元素要寫作"rest"。本項目的后臺接口基本都是采用RESTFUL規(guī)范,具體路由的詳細講解可以看官網(wǎng)鏈接
五.部署
項目線上部署采用PM2管理node進程,部署時把src,view,www,pm2.json,production.js放到服務(wù)器上。安裝好pm2后運行
pm2 start pm2.json
注意pm2.json里需要修改cwd為服務(wù)器上你項目的目錄。本項目前后端是一個服務(wù),不存在所以沒有用nginx代理。thinkJs部署相關(guān)可以看這里
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/102092.html
摘要:插件機制可以說是自定義的鉤子函數(shù)。首先在新建文件夾,新建文件以為例更新內(nèi)容緩存里對應(yīng)的數(shù)組表示鉤子函數(shù)的調(diào)用名,具體調(diào)用的是下面的方法。 一.簡介 這個個人博客網(wǎng)站最初制作的目的就是練習(xí)使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。 項目thi...
摘要:插件機制可以說是自定義的鉤子函數(shù)。首先在新建文件夾,新建文件以為例更新內(nèi)容緩存里對應(yīng)的數(shù)組表示鉤子函數(shù)的調(diào)用名,具體調(diào)用的是下面的方法。 一.簡介 這個個人博客網(wǎng)站最初制作的目的就是練習(xí)使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。 項目thi...
摘要:首先看下的代碼編譯前刪除之前編譯生成的靜態(tài)資源首先需要改的是入口文件,因為是多頁面應(yīng)用,需要多個入口文件來保證打包成不同的。 一.項目簡介 ? ? 本項目使用vue作為前端框架,thinkJs作為后端框架,構(gòu)建個人博客網(wǎng)站,頁面分為博客展示和后臺管理,主要目的是學(xué)習(xí)使用thinkJs。現(xiàn)在只完成了主要的博客增刪改功能,發(fā)現(xiàn)webpack的配置遇到了一些坑,這里先記錄下。項目目錄結(jié)構(gòu)如下...
摘要:首先看下的代碼編譯前刪除之前編譯生成的靜態(tài)資源首先需要改的是入口文件,因為是多頁面應(yīng)用,需要多個入口文件來保證打包成不同的。 一.項目簡介 ? ? 本項目使用vue作為前端框架,thinkJs作為后端框架,構(gòu)建個人博客網(wǎng)站,頁面分為博客展示和后臺管理,主要目的是學(xué)習(xí)使用thinkJs。現(xiàn)在只完成了主要的博客增刪改功能,發(fā)現(xiàn)webpack的配置遇到了一些坑,這里先記錄下。項目目錄結(jié)構(gòu)如下...
摘要:一入冬懶癌發(fā)作,給自己找點事干。之前博客程序?qū)戇^幾次,的寫過兩次,用寫過,隨著版本從升級到之前的博客程序也做過升級。這里主要記錄一下開發(fā)過程中遇到的問題和解決方法。后端使用守護進程即可。 一入冬懶癌發(fā)作,給自己找點事干。之前博客程序?qū)戇^幾次,php 的寫過兩次,nodejs 用 ThinkJS 寫過,隨著 ThinkJS 版本從1.x 升級到 2.x 之前的博客程序也做過升級。但是因為...
閱讀 2648·2023-04-26 00:07
閱讀 2436·2021-11-15 11:37
閱讀 643·2021-10-19 11:44
閱讀 2170·2021-09-22 15:56
閱讀 1726·2021-09-10 10:50
閱讀 1504·2021-08-18 10:21
閱讀 2571·2019-08-30 15:53
閱讀 1635·2019-08-30 11:11