搜尋
首頁web前端js教程Node.js框架 ThinkJS 開發 controller講解

Node.js框架 ThinkJS 開發 controller講解

Jul 17, 2017 pm 04:00 PM
javascriptnode.js

原創:荊秀網網頁即時推送 | 轉載請註明出處
連結:

本系列教學以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().

那麼可能有人會說:看起來 __beforeinit 是一樣的用途。老規矩,來看程式碼:


// 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(&#39;_target_url&#39;).value;var _wait_seconds = document.getElementById(&#39;_wait_seconds&#39;).value;if (_target_url == &#39;&#39;) 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(&#39;_count&#39;).innerHTML = cnt;window.setTimeout(function () {thisCount(--cnt);}, 1000);};window.attachEvent ? window.attachEvent(&#39;onload&#39;, thisLoad) : window.addEventListener(&#39;load&#39;, thisLoad);</script>

以上是Node.js框架 ThinkJS 開發 controller講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

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

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

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

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

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

JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

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

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

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

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

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

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

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

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

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

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

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

熱工具

SecLists

SecLists

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

Safe Exam Browser

Safe Exam Browser

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

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

MantisBT

MantisBT

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