Heim > Artikel > Web-Frontend > Erklärung des ThinkJS-Entwicklungscontrollers für das Node.js-Framework
Original: Jingxiu.com Webseite Instant Push |. Bitte geben Sie die Quelle für den Nachdruck an
Link:
Diese Tutorialreihe basiert auf ThinkJS v2.x Version (offizielle Website) Beispiele werden vorgestellt und das Tutorial konzentriert sich auf praktische Vorgänge.
In diesem Artikel wird weiterhin die Verwendung des Controllers erläutert.
Wenn Sie beim Instanziieren des Objekts etwas tun möchten, ist die Konstruktormethode die beste Wahl. Der von ES6 bereitgestellte Konstruktor ist constructor
.
Die Konstruktormethode ist die Standardmethode der Klasse. Diese Methode wird automatisch aufgerufen, wenn eine Objektinstanz durch den neuen Befehl generiert wird. Eine Klasse muss eine Konstruktormethode haben, wenn sie nicht explizit definiert ist, wird standardmäßig eine leere Konstruktormethode hinzugefügt.
Methoden
ECMAScript 6 Erste Schritte Autor: Ruan Yifeng
Die Stärke von thinkjs liegt darin, dass wir nicht nur folgen können Die Regeln export default class
deklarieren die Klasse selbst und bieten außerdem eine Methode zum dynamischen Erstellen der Klasse: think.controller
.
Aber die von thinkjs dynamisch erstellte Klasse verfügt nicht über constructor
, sondern stellt ein init
als Alternative zur Konstruktormethode bereit, das auf die gleiche Weise wie constructor
verwendet wird.
Es gibt auch Beispiele für die Verwendung der init
-Methode im vorherigen Artikel (Node.js Domestic MVC Framework ThinkJS Development Controller Chapter Base Class and Inheritance Chain Part), schauen Sie sich den Code noch einmal an:
// 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 参数');} }}
Das bedeutet natürlich nicht, dass Sie die Methode constructor
nicht verwenden können. Wenn Sie wie ich sind, sind Sie es gewohnt, die Klasse selbst mit export default class
zu deklarieren , können Sie weiterhin die Standardmethode constructor
verwenden.
Informationen zur Methode zum dynamischen Erstellen von Klassen in thinkjs finden Sie in der offiziellen Dokumentation. Sie wird hier nicht wiederholt.
thinkjs hat mehrere sehr nützliche magische Methoden implementiert, die eine große Benutzerfreundlichkeit für die manuelle Entwicklung bieten, z. B. ~
Wie der Name schon sagt, wird die Voroperation ausgeführt, bevor die spezifische Aktion im Controller ausgeführt wird, was „ausgeführt vor xxx“ bedeutet. Schauen wir uns den Code an:
// 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().
Dann werden einige Leute vielleicht sagen: Es scheint, dass __before
und init
denselben Zweck haben. Schauen Sie sich wie gewohnt den Code an:
// 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().
Sehen Sie ihn? Es gibt noch eine Reihenfolge der Ausführung, nehmen wir eine kompliziertere:
// 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().
Nun, Sie würden „erwartet“ sagen~
Nachdem Sie die Voroperationen verstanden haben, sind die Nachoperationen nicht schwer zu verstehen:
// 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().
Häh? Etwas scheint nicht zu stimmen. . . __after
Nicht ausgeführt.
Das liegt natürlich nicht daran, dass __after
oben geschrieben wurde indexAction
! Ändern Sie den Code:
// 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().
Diesmal ist es in Ordnung und entspricht den erwarteten Ergebnissen.
Ich weiß, dass Sie bemerkt haben, dass der Code return this.end()
von indexAction
nach __after
verschoben wurde.
this.end()
führt intern den Vorgang Node.js HTTP Response.end() aus und zeigt an, dass der gesamte Antwortfluss beendet ist. Wenn Sie also __after
aktivieren möchten, verwenden Sie diesen Code ist Es muss im Inneren ausgeführt werden __after
.
Diese magische Methode ist etwas Besonderes. Sie wird nicht wie die beiden vorherigen magischen Methoden zur Ausführung an einem bestimmten Prozessknoten verwendet, sondern teilt einige der Verantwortlichkeiten von init
: Wird verwendet, um zu erkennen, wenn die Aktion, auf die ein Controller zugreift, nicht definiert ist. __call
übernimmt den Vorgang.
// 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.
Sie können sehen, dass das Framework testAction
zur Verarbeitung ausgeführt wird, wenn der Zugriff __call
nicht vorhanden ist. Unsere Verarbeitung besteht darin, den Fehler aufzuzeichnen und Beenden Sie die Antwortausgabe.
Der Beispielcode platziert __call
in der Unterklasse der zweiten Ebene, normalerweise in der Basisklasse, die die illegale Zugriffsverarbeitung aller Unterklassen steuern kann.
Tipp: Diese Methode kann nur verwendet werden, um die Situation zu erfassen, in der die Aktion nicht vorhanden ist. Wenn der Controller jedoch nicht vorhanden ist, wird direkt ein 404-Fehler ausgelöst (vom Framework übernommen). und kann nicht eingreifen.
Wenn Sie die Situation abfangen möchten, in der der Controller nicht vorhanden ist, müssen Sie die Fehlerklasse des Frameworks erweitern, was in einem anderen Artikel beschrieben wird.
thinkjs offizielle Website-API verfügt über eine Schnittstelle zum Instanziieren eines anderen Controllers, erklärt jedoch nicht die spezifische Verwendung davon:
//实例化 home 模块下 user controllerlet instance = think.controller('user', http, 'home');
Normalerweise kann diese Methode verwendet werden, um einen Controller auf Geschwisterebene zu instanziieren, um Daten abzurufen oder um einen Geschäftsprozess auszulösen usw. Schauen wir uns den Code an:
// 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
Es ist ersichtlich, dass thinkjs eine Möglichkeit bietet, einen Controller bei Bedarf zu instanziieren und seine Methoden auszuführen.
Auf den ersten Blick kommt diese Methode dem Ergebnis von this.redirect
sehr nahe (außer dass die magische Methode von __call
nicht ausgelöst wird). Was nützt es also, wenn thinkjs diese Methode bereitstellt? Schauen wir uns den Code an:
// 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 对象是 ThinkJS 对 req 和 res 重新包装的一个对象,而非 Node.js 内置的 http 对象。
Action 里如果想获取该对象,可以通过 this.http 来获取。
thinkjs 官网
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/img/logo.png" alt="XxuYou" width="60"></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>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>