Heim > Web-Frontend > js-Tutorial > Erklärung des ThinkJS-Entwicklungscontrollers für das Node.js-Framework

Erklärung des ThinkJS-Entwicklungscontrollers für das Node.js-Framework

巴扎黑
Freigeben: 2017-07-17 16:00:11
Original
2325 Leute haben es durchsucht

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.

Konstruktormethode

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

Init und Konstruktor

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 参数');}
  }}
Nach dem Login kopieren

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.

Magische Methoden

thinkjs hat mehrere sehr nützliche magische Methoden implementiert, die eine große Benutzerfreundlichkeit für die manuelle Entwicklung bieten, z. B. ~

__before-Präfix-Operation

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().
Nach dem Login kopieren

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().
Nach dem Login kopieren

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().
Nach dem Login kopieren

Nun, Sie würden „erwartet“ sagen~

__nach dem Post -Operationen

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().
Nach dem Login kopieren

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().
Nach dem Login kopieren

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.

__call no-op

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.
Nach dem Login kopieren

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.

Externe Aufrufmethode

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');
Nach dem Login kopieren

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
Nach dem Login kopieren

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;
  }}
Nach dem Login kopieren

这是一个助手 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('');});
  }}
Nach dem Login kopieren


<!-- 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>

Nach dem Login kopieren


// Controller 内调用方式indexAction() {
  // 业务流程。。。
  let complete = think.controller(&#39;complete&#39;, this.http, &#39;common&#39;);
  return complete.display(&#39;操作成功!&#39;, &#39;/&#39;, 5);}
Nach dem Login kopieren

以上新增的 src/common/controller/complete.js 是一个非侵入式的成功业务处理页面,其内部运行与兄弟 Controller src/common/controller/error.js 类似。

以上新增的 view/common/complete_200.html 则是相关的过渡页面的模版。其中存在三个占位符(分别对应 display 方法的入參):

  • COMPLETE_MESSAGE 用于操作成功的文字提示内容

  • TARGET_URL 用于稍后会自动进入的目标 url

  • WAIT_SECONDS 用于页面过渡时间,单位是秒

实现原理其实非常简单,阅读一下两个新增的代码就能明白。

扩展应用:快速构建 REST API

其实这部分因为太简答,我本来是不想写的。不过考虑到教程的完整性,还是写一下比较好。

REST 的概念介绍这里不再赘述,有兴趣的可以自行搜索。

thinkjs 的官网说到:

自动生成 REST API,而无需写任何的代码。

此言不虚,创建 Controller 时只要增加一个参数(thinkjs controller [name] --rest),即可生成一个能够操作数据库表的 REST API。

当然操作的约定也还是有的:

  • GET /ticket #获取ticket列表

  • GET /ticket/12 #查看某个具体的ticket

  • POST /ticket #新建一个ticket

  • PUT /ticket/12 #更新ticket 12

  • DELETE /ticket/12 #删除ticekt 12

遵从了上述操作约定,的确是可以直接操作数据库表内的数据了。

只是这样的 API 只不过是一个“裸奔”状态的 API,还是不能直接投入使用。因为它不仅要求请求方熟悉所有的数据表结构,还要依赖请求方来维护多表数据之间的关联性,更不用提什么操作路径的映射、字段映射、返回数据的映射等等问题了。

就算 thinkjs 还提供了字段过滤、自定义 GET/POST/PUT/DELETE 方法来进行更多的定制,那么最终的结果很可能是在当前的 API 外面再包裹一层能够提供操作路径映射、鉴权令牌发放和识别、字段映射、关联数据维护等等。

当然作为一个开发框架,thinkjs 确实已经做的够多了,足够优秀了,因此我们还是需要像构建一个应用系统那样去完整构建一个可供实施的 REST API 的生产模型。

Das obige ist der detaillierte Inhalt vonErklärung des ThinkJS-Entwicklungscontrollers für das Node.js-Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage