原創:荊秀網網頁即時推送 | 轉載請註明出處
連結:
本系列教學以ThinkJS v2.x 版本(官網)為例進行介紹,教程以實際操作為主。
本篇繼續講解 Controller 的使用。
建構方法
如果想要在物件實例化的時候做點事情,建構方法是最好的選擇。 ES6 提供的建構方法是 constructor
。
constructor方法是類別的預設方法,透過new指令產生物件實例時,自動呼叫方法。一個類別必須有constructor方法,如果沒有明確定義,一個空的constructor方法會被預設為添加。
方法
ECMAScript 6 入門作者:阮一峰
init 與constructor
thinkjs 強大的地方在於,我們不僅可以規規矩矩的export default class
自己宣告Class ,也提供了動態建立Class 的方法:think.controller
。
但是thinkjs 動態建立的Class 沒有constructor
,而是提供了一個init
作為建構方法的替代方法,該方法的使用方式與constructor
一致。
上一篇文章(Node.js 國產MVC 框架ThinkJS 開發controller 篇基底類別與繼承鏈部分)中也有init
方法的使用範例,再看程式碼:
// src/home/controller/base.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);// 要求全部 url 必须携带 auth 参数let auth = this.get('auth');if (think.isEmpty(auth)) { return this.error(500, '全部 url 必须携带 auth 参数');} }}
當然這並不是表示不能使用constructor
方法了,假如你是像我一樣習慣使用export default class
自己宣告Class 的筒子,還是可以用回標準的constructor
方法的。
thinkjs 動態建立 Class 的方法請參考官方文檔,這裡不再贅述。
魔術方法
thinkjs 實現了幾個很有用的魔術方法,為開發提供了極大的便利,手動點讚~
__before 前置動作
顧名思義,前置操作會搶先在Controller 中具體的Action 執行之前執行,就是「在xxx 之前執行」的意思。來看程式碼:
// src/home/controller/user.js'use strict';export default class extends think.controller.base { __before() {console.log('this is __before().'); } indexAction() {console.log('this is indexAction().');return this.end(); }}// 访问 /home/user/index 的执行结果如下:// this is __before().// this is indexAction().
那麼可能有人會說:看起來 __before
跟 init
是一樣的用途。老規矩,來看程式碼:
// src/home/controller/user.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is init().'); } __before() {console.log('this is __before().'); } indexAction() {console.log('this is indexAction().');return this.end(); }}// 访问 /home/user/index 的执行结果如下:// this is init().// this is __before().// this is indexAction().
看到了嗎?執行還是有先後順序的,再來個複雜一點的:
// src/home/controller/base.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is base.init().'); }}// src/home/controller/user.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is user.init().'); } __before() {console.log('this is user.__before().'); } indexAction() {console.log('this is user.indexAction().');return this.end(); }}// 访问 /home/user/index 的执行结果如下:// this is base.init().// this is user.init().// this is user.__before().// this is user.indexAction().
好吧,你會說「意料之中」~
__after 後置操作
明白了前置操作,後置操作也不難理解,看程式碼:
// src/home/controller/user.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is init().'); } __before() {console.log('this is __before().'); } __after() {console.log('this is __after().'); } indexAction() {console.log('this is indexAction().');return this.end(); }}// 访问 /home/user/index 的执行结果如下:// this is init().// this is __before().// this is indexAction().
咦?貌似有地方不對。 。 。 __after
沒執行。
這當然不是 __after
寫在 indexAction
上面導致的!修改程式碼:
// src/home/controller/user.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is init().'); } __before() {console.log('this is __before().'); } __after() {console.log('this is __after().');return this.end(); } indexAction() {console.log('this is indexAction().'); }}// 访问 /home/user/index 的执行结果如下:// this is init().// this is __before().// this is indexAction().// this is __after().
這次 OK 了,和預期的結果一致。
我知道細心的你已經注意到有句代碼 return this.end()
從 indexAction
移動到 __after
裡面了。
this.end()
內部執行了Node.js HTTP response.end() 操作,表示整個回應流結束了,因此如果想要啟用__after
的話,這句程式碼就要放在__after
裡面運作。
__call 空操作
這個魔術方法有點特殊,它不像前兩個魔術方法一樣用於在某個流程節點打點運行,而是分擔了init
的部分職責:用來偵測某個Controller 被存取的Action 並未定義的情況下,由__call
來接手運作。
// src/home/controller/user.js'use strict';export default class extends think.controller.base { init(...args) {super.init(...args);console.log('this is init().'); } __call() {console.log(this.http.action + 'Action is not exists.');return this.end(); } indexAction() {console.log('this is indexAction().');return this.end(); }}// 访问 /home/user/test 的执行结果如下:// this is init().// testAction is not exists.
可以看到當存取的testAction
不存在時,框架會執行__call
來處理,我們的處理是記錄錯誤並結束響應輸出。
範例程式碼是將 __call
放在了二級子類別中,通常是放在基底類別中,可以管控全部子類別的非法存取處理。
提示:本方法只能用來捕捉 Action 不存在的情況,但假如 Controller 不存在,會直接觸發 404 錯誤(被框架接管)而無法干涉。
如要捕捉 Controller 不存在的情況,需要擴展框架的錯誤類,另文描述。
外部呼叫方式
thinkjs 官網API 中有實例化另外一個Controller 的接口,但是並沒有說明這個具體有什麼用途:
//实例化 home 模块下 user controllerlet instance = think.controller('user', http, 'home');
那麼通常這個方法可以用來實例化兄弟層級Controller ,或是取得資料、或觸發一個業務流程等,來看程式碼:
// src/home/controller/user.js 增加_getPoints() { return 8000;}// src/home/controller/index.jslet instance = think.controller('user', this.http, 'home');let points = instance._getPoints();console.log(points); // 打印:8000instance.indexAction(); // 与直接执行 /home/user/index 是一样的效果instance.testAction(); // 报错 [Error] TypeError: instance.testAction is not a function
可見是thinkjs 提供了一個按需實例化某個Controller 並運行其方法的途徑。
乍看之下這個方式與this.redirect
運行結果非常接近(除了不會觸發__call
的魔術方法以外),那麼thinkjs 提供這個方式有什麼用呢?來看程式碼:
// src/home/controller/util.js'use strict';export default class extends think.controller.base { calcGPSDistance(lat, lng){// 计算 GPS 两点直线距离return distance; } calcBaiduDistance(lat, lng){// 计算 百度大地坐标 两点直线距离return distance; } calcSosoDistance(lat, lng){// 计算 Soso坐标 两点直线距离return distance; }}
这是一个助手 Controller,一个“隐身”的 Controller,从 url 是无法直接访问到的,因为它的所有方法名均没有 Action 后缀。
这个场景下,运行时实例化 Controller 并操作其方法的方式就派上用场了。
内置 http 对象
控制器在实例化时,会将 http 传递进去。该 http 对象是 ThinkJS 对 req 和 res 重新包装的一个对象,而非 Node.js 内置的 http 对象。
Action 里如果想获取该对象,可以通过 this.http 来获取。
thinkjs 官网
扩展应用:增加一个 n 秒后自动跳转的过渡页功能
thinkjs 框架并没有给我们准备这样一个过渡页面的功能,那么我们可以自己实现一个来练练手,上代码:
// src/common/controller/complete.js'use strict';export default class extends think.controller.base { /** * 显示中转页面 * * 调用方式: * let complete = think.controller('complete', this.http, 'common'); * return complete.display('应用新增成功!', '/', 5); * * @param msg 提示文字,支持 HTML * @param url 后续自动跳转的目标地址 * @param delay 停留秒数 * @returns {think.Promise} */ display(msg, url='', delay=3) {let tpl = 'common/complete/200';let opt = think.extend({}, {type: 'base', file_depr: '_', content_type: 'text/html'});this.fetch(tpl, {}, opt).then(content => { content = content.replace(/COMPLETE_MESSAGE/g, msg); if (url) {content = content.replace(/TARGET_URL/g, url);content = content.replace(/WAIT_SECONDS/g, delay); }; this.type(opt['content_type']); return this.end(content);}).catch(function(err){ return this.end('');}); }}
<!-- view/common/complete_200.html --><!DOCTYPE html><html><head><title>正在跳转 - 荆秀网</title></head><body><p class="header"><p class="wrap"><p class="logo"><a href="/"><img src="/static/imghwm/default1.png" data-src="/static/img/logo.png" class="lazy" alt="XxuYou" style="max-width:90%"></a></p><p class="headr"> </p></p></p><p class="wrap"><p style="margin-top:20px;height:100px;background:url(/static/img/200.gif) top center no-repeat;"></p><h1 id="COMPLETE-MESSAGE">COMPLETE_MESSAGE</h1><p class="error-msg"><pre class="brush:php;toolbar:false">提示:页面将在 <span id="_count">WAIT_SECONDS</span> 秒后重定向到 <a href="TARGET_URL">TARGET_URL</a><script>var thisLoad = function () {var _target_url = document.getElementById('_target_url').value;var _wait_seconds = document.getElementById('_wait_seconds').value;if (_target_url == '') return false;if (/^\d+$/.test(_wait_seconds) == false || _wait_seconds < 1 || _wait_seconds >= 3600) {try {document.location.replace(_target_url);} catch(e) {};} else {thisCount(_wait_seconds);window.setTimeout(function () {try {document.location.replace(_target_url);} catch(e) {};}, _wait_seconds*1000);};return true;};var thisCount = function (cnt) {if (cnt < 0) return false;document.getElementById('_count').innerHTML = cnt;window.setTimeout(function () {thisCount(--cnt);}, 1000);};window.attachEvent ? window.attachEvent('onload', thisLoad) : window.addEventListener('load', thisLoad);</script>
以上是Node.js框架 ThinkJS 開發 controller講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver CS6
視覺化網頁開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。