Heim > Web-Frontend > js-Tutorial > In Komponenten denken

In Komponenten denken

Joseph Gordon-Levitt
Freigeben: 2025-02-21 09:54:16
Original
155 Leute haben es durchsucht

In Komponenten denken

Key Takeaways

  • Der Komponentenansatz zur Schnittstellenentwicklung bietet Vorteile gegenüber herkömmlichen MVC- und MVVM -Frameworks und konzentriert
  • Komponenten sollten für die Wiederverwendung ausgelegt sein, von der Geschäftsdomäne distanziert und an verschiedene Kontexte anpassbar sind. Dieser Ansatz kann bei der Erstellung einer suggestiven Texteingangskomponente veranschaulicht werden, die universell verwendet werden kann, und nicht eine bestimmte Typ-Ahead-Hilfe-Suchkomponente.
  • Schnittstellen in komponierbare Komponenten einteilen, vereinfacht nicht nur den Entwicklungsprozess, sondern erleichtert auch isolierte Tests. Komponenten sind unabhängig voneinander und ermöglichen Änderungen und Ergänzungen, ohne das Gesamtsystem zu stören.
Webkomponenten, React, Polymer, Flug - alle sind zum Erstellen von Grenzflächenkomponenten bestimmt. Dies ist ein anderes Toolset als das Big MVC- und MVVM -Frameworks und erfordert eine andere Denkweise, wenn Sie planen, wie Sie Ihre Benutzeroberfläche implementieren. Während ich noch Modelle wie MVC für Serveranwendungen verwende, bin ich ein dedizierter Konvertit auf die Vorteile eines Komponentenansatzes für die Schnittstellenentwicklung. In diesem Artikel werde ich skizzieren, wie das Denken in Komponenten vom Denken in MVC unterscheidet und diesen Ansatz in einem realen Beispiel implementiert.

In meinem Kopf lautet der Headspace für MVC -Design: „Wie modelliere ich meine Geschäftsdomäne? Wie modelliere ich die Prozesse der Interaktion mit dieser Domäne? Wie modelliere ich die Schnittstelle, um diese Prozesse zu erleichtern? “ Ich bin der Meinung, dass dieser Headspace kein gutes Komponentendesign erleichtert. Tatsächlich ist es das polare Gegenteil dafür, wie Sie denken sollten, wenn Sie eine Schnittstelle in komponierbare Komponenten zerlegen. Bestenfalls erhalten Sie Micro -Apps. Im schlimmsten Fall bauen Sie Gottkomponenten auf. Das Letzte, was Sie tun möchten, ist, Ihre Geschäftsdomäne als Komponenten zu modellieren. Was Sie anstreben sollten, um zu modellieren, sind die kleinsten abstrakten Interaktionsabschnitte, die Sie beschreiben können.

Entwurf für Wiederverwendung

Anstelle von „Wie mache ich dieses entlehnende Warnwarnungsfeld?“ Fragen Sie sich: „Wenn ich neue HTML -Elemente hinzufügte, um diese Interaktion zu erleichtern, was wären sie?“. Ich finde, dies führt zu Komponenten, die sicher von der Geschäftsdomäne entfernt sind und von Natur aus in verschiedenen Kontexten wiederverwendbarsten sind.

Machen Sie als ein weiteres Beispiel keine Typ-Ahead-Hilfe-Suchkomponente, die überall verwendet werden, wo Sie das Durchsuchen des Help-Systems zulassen möchten, und erstellen Sie eine suggestive Texteingangskomponente, die über die Interaktionen zur Bereitstellung von Eingabebedingungen informiert ist. Nehmen Sie anschließend eine Hilfesuche -API -Datenkomponente durch, die weiß, wie Anforderungen für Daten empfangen werden, und interagieren Sie mit der Help -Suche API und Broadcast -Ergebnisse. Jetzt benötigen die Tests Ihres Suggestivtexteingangs keine APIs verspottet. Wenn Sie aufgefordert werden, einem Feld „Tag“ Vorschläge hinzuzufügen, können Sie Ihre vorhandene Suggestiv -Texteingabetomponente fallen lassen, eine einfache Datenkomponente, die Gespräche spricht zur Tag -API und fertig!

Praktisches Beispiel - „Projektliste“

Für ein konkretes Beispiel sehen wir uns die Implementierung einer einfachen Schnittstelle als isolierte Komponenten an. Das folgende Modell ist eine Extraktion aus dem 1-zu-1-Projektsystem von 99Designs. Während die Benutzeroberfläche drastisch vereinfacht wurde, ist das JavaScript, dem wir aufbauen werden, der Produktionscode von unserer Website zum Zeitpunkt des Schreibens. Hier ist der Wireframe:

In Komponenten denken

Was wir haben, ist die Navigation zwischen drei Projektlisten - aktiv, Entwürfe und archiviert. Jedes Projekt hat eine Aktion, die darauf aus ausgeführt werden kann-archivieren ein aktives Projekt, das Löschen eines Entwurfs oder die Wiedereinaktivierung eines archivierten Projekts. Im App -Design -Denken würden wir mit der Modellierung eines Projekts beginnen und ihm Methoden wie „Archiv“ und „Löschen“ sowie eine „Status“ -Fahrung geben, um zu verfolgen, in welcher der drei Listen es gehört. Genau das, was wir vermeiden wollen, werden wir uns nur mit den Interaktionen und dem, was nötig ist, um sie zu erleichtern, uns kümmern.

Im Kern haben wir eine Aktion pro Zeile. Wenn diese Aktion ausgeführt wird, möchten wir die Zeile aus der Liste entfernen. Wir haben bereits ein projektspezifisches Domänenwissen abgelegt! Darüber hinaus zählen wir mit der Anzahl der viele Elemente in jeder Liste. Um den Umfang dieses Artikels zurückzuhalten, gehen wir davon aus, dass jede serverseitige Seite mit der Registerkartennavigation eine vollständige Aktualisierung der Seite verursacht. Da wir nicht die Abhängigkeit von JavaScript erzwingen müssen, werden unsere Aktionsschaltflächen Elemente mit Submit -Ereignishandlern sein, die asynchron die Aktion des Formulars ausführen und ein Ereignis übertragen, wenn es abgeschlossen ist.

Hier ist ein HTML für eine einzelne Projektzeile:

<span><span><span><li</span>></span>
</span>  <span><span><span><a</span> href<span>="/projects/99"</span> title<span>="View project"</span>></span>Need sticker designs for XYZ Co.<span><span></a</span>></span>
</span>  <span><span><span><div</span> class<span>="project__actions"</span>></span>
</span>    <span><span><span><a</span> href<span>="/projects/99"</span> class<span>="button"</span>></span>View<span><span></a</span>></span>
</span>    <span><span><span><form</span> class<span>="action"</span> action<span>="/projects/99/archive"</span> method<span>="post"</span>></span>
</span>        <span><span><span><button</span>></span>Archive<span><span></button</span>></span>
</span>    <span><span><span></form</span>></span>
</span>  <span><span><span></div</span>></span>
</span><span><span><span></li</span>></span></span>
Nach dem Login kopieren
Nach dem Login kopieren

Ich werde den Flug verwenden, um unsere Komponenten zu erstellen. Der Flug ist derzeit unsere Standard -JS -Komponentenbibliothek bei 99Designs aus den Gründen, die ich in meinem vorherigen SitePoint -JavaScript -Artikel beschrieben habe.

Hier ist unsere asyncForm -Komponente zum Abwickeln der Formulareingabe und der Übertragung eines Ereignisses:

<span>define(function(require) {
</span>  <span>'use strict';
</span>
  <span>var defineComponent = require('flight/lib/component');
</span>
  <span>function <span>AsyncForm</span>() {
</span>    <span>this.defaultAttrs({
</span>      <span>broadcastEvent: 'uiFormProcessed'
</span>    <span>});
</span>
    <span>this.after('initialize', function() {
</span>      <span>this.on(this.node, 'submit', this.asyncSubmit.bind(this));
</span>    <span>});
</span>
    <span>this.asyncSubmit = function(event) {
</span>      event<span>.preventDefault();
</span>      $<span>.ajax({
</span>        <span>'url': this.$node.attr('action'),
</span>        <span>'dataType': 'json',
</span>        <span>'data': this.$node.serializeArray(),
</span>        <span>'type': this.$node.attr('method')
</span>      <span>}).done(function(response<span>, data</span>) {
</span>        <span>this.$node.trigger(this.attr.broadcastEvent, data);
</span>      <span>}.bind(this)).fail(function() {
</span>        <span>// error handling excluded for brevity
</span>      <span>});
</span>    <span>};
</span>  <span>}
</span>
  <span>return defineComponent(AsyncForm);
</span><span>});</span>
Nach dem Login kopieren
Nach dem Login kopieren

Wir behalten eine strenge Richtlinie für die Verwendung von Klassenattributen für JavaScript bei. Daher fügen wir unseren Aktionsformularen ein Data-async-Formattribut hinzu und addieren unsere Komponenten an alle übereinstimmenden Formulare wie SO:

<span><span><span><li</span>></span>
</span>  <span><span><span><a</span> href<span>="/projects/99"</span> title<span>="View project"</span>></span>Need sticker designs for XYZ Co.<span><span></a</span>></span>
</span>  <span><span><span><div</span> class<span>="project__actions"</span>></span>
</span>    <span><span><span><a</span> href<span>="/projects/99"</span> class<span>="button"</span>></span>View<span><span></a</span>></span>
</span>    <span><span><span><form</span> class<span>="action"</span> action<span>="/projects/99/archive"</span> method<span>="post"</span>></span>
</span>        <span><span><span><button</span>></span>Archive<span><span></button</span>></span>
</span>    <span><span><span></form</span>></span>
</span>  <span><span><span></div</span>></span>
</span><span><span><span></li</span>></span></span>
Nach dem Login kopieren
Nach dem Login kopieren

Jetzt können wir die Aktion ausführen und ein Ereignis übertragen, das den Dom -Baum zum Erfolg ausbreitet. Der nächste Schritt ist es, dieses Ereignis zu hören und die Zeile zu entfernen, zu der sie sprudelt. Dafür haben wir abnehmbar:

<span>define(function(require) {
</span>  <span>'use strict';
</span>
  <span>var defineComponent = require('flight/lib/component');
</span>
  <span>function <span>AsyncForm</span>() {
</span>    <span>this.defaultAttrs({
</span>      <span>broadcastEvent: 'uiFormProcessed'
</span>    <span>});
</span>
    <span>this.after('initialize', function() {
</span>      <span>this.on(this.node, 'submit', this.asyncSubmit.bind(this));
</span>    <span>});
</span>
    <span>this.asyncSubmit = function(event) {
</span>      event<span>.preventDefault();
</span>      $<span>.ajax({
</span>        <span>'url': this.$node.attr('action'),
</span>        <span>'dataType': 'json',
</span>        <span>'data': this.$node.serializeArray(),
</span>        <span>'type': this.$node.attr('method')
</span>      <span>}).done(function(response<span>, data</span>) {
</span>        <span>this.$node.trigger(this.attr.broadcastEvent, data);
</span>      <span>}.bind(this)).fail(function() {
</span>        <span>// error handling excluded for brevity
</span>      <span>});
</span>    <span>};
</span>  <span>}
</span>
  <span>return defineComponent(AsyncForm);
</span><span>});</span>
Nach dem Login kopieren
Nach dem Login kopieren

Auch hier fügen wir unseren Projektzeilen ein datenauslösbares Attribut hinzu und fügen die Komponente den Zeilenelementen hinzu:

<span>AsyncForm.attachTo('[data-async-form]');</span>
Nach dem Login kopieren

fertig! Zwei kleine Komponenten mit jeweils einem Ereignis, und wir haben die drei Arten von Aktionen in unseren drei Formen auf eine Weise behandelt, die sich anmutig verschlechtert. Nur noch eine Sache, und das ist unsere Zählung auf jeder Registerkarte. Sollte einfach genug sein, wir brauchen alles, was wir brauchen, um die Anzahl der aktiven Registerkarten jedes Mal um eins um eins zu verringern, wenn eine Reihe entfernt wird. Aber warte! Wenn ein aktives Projekt archiviert wird, muss die archivierte Anzahl zunehmen, und wenn ein archiviertes Projekt wieder aktiviert wird, muss die aktivierte Anzahl zunehmen. Lassen Sie uns zunächst eine Count -Komponente erstellen, die Anweisungen erhalten kann, um seine Nummer zu ändern:

<span>define(function(require) {
</span>  <span>'use strict';
</span>
  <span>var defineComponent = require('flight/lib/component');
</span>
  <span>function <span>Removable</span>() {
</span>    <span>this.defaultAttrs({
</span>      <span>'removeOn': 'uiFormProcessed'
</span>    <span>});
</span>
    <span>this.after('initialize', function() {
</span>      <span>this.on(this.attr.removeOn, this.remove.bind(this));
</span>    <span>});
</span>
    <span>this.remove = function(event) {
</span>      <span>// Animate row removal, remove DOM node, teardown component
</span>      $<span>.when(this.$node
</span>        <span>.animate({'opacity': 0}, 'fast')
</span>        <span>.slideUp('fast')
</span>      <span>).done(function() {
</span>        <span>this.$node.remove();
</span>      <span>}.bind(this));
</span>    <span>};
</span>  <span>}
</span>
  <span>return defineComponent(Removable);
</span><span>});</span>
Nach dem Login kopieren

Unsere Zählung würde in HTML als etwas wie 4 dargestellt. Da die Anzahl auf Dokumentenebene Ereignisse hört, werden wir die Eventeigenschaft null machen. Dies erzwingt die Verwendung von es, um ein Ereignis zu definieren, das diese Instanz anhören sollte, und verhindern, dass mehrere Zählinstanzen auf demselben Ereignis nach Anweisungen hören.

.
<span>Removable.attachTo('[data-removable]');</span>
Nach dem Login kopieren

Das letzte Stück des Puzzles erhält unsere abnehmbaren Instanzen, um ein Ereignis mit einem Modifikator zu ihren jeweiligen Zählen zu entlassen, wenn sie entfernt werden. Wir möchten sicherlich keine Kopplung zwischen den Komponenten, daher geben wir ein abnehmbares Attribut, das eine Reihe von Ereignissen enthält, wenn es entfernt wird:
<span>define(function(require) {
</span>  <span>'use strict';
</span>
  <span>var defineComponent = require('flight/lib/component');
</span>
  <span>function <span>Count</span>() {
</span>    <span>this.defaultAttrs({
</span>      <span>'event': null
</span>    <span>});
</span>
    <span>this.after('initialize', function() {
</span>      <span>this.on(document, this.attr.event, this.update.bind(this));
</span>    <span>});
</span>
    <span>this.update = function(event<span>, data</span>) {
</span>      <span>this.$node.text(
</span>        <span>parseInt(this.$node.text(), 10) + data.modifier
</span>      <span>);
</span>    <span>}
</span>  <span>}
</span>
  <span>return defineComponent(Count);
</span><span>});</span>
Nach dem Login kopieren

Jetzt tritt die Kopplung zwischen Zähl und Wechsel im verwendungs ​​casespezifischen Seitenskript auf, in dem wir unsere Komponenten an das DOM anhängen:
<span>Count.attachTo(
</span>  <span>'[data-counter="active"]',
</span>  <span>{'event': 'uiActiveCountChanged'}
</span><span>);
</span>
<span>Count.attachTo(
</span>  <span>'[data-counter="draft"]',
</span>  <span>{'event': 'uiDraftCountChanged'}
</span><span>);
</span>
<span>Count.attachTo(
</span>  <span>'[data-counter="archived"]',
</span>  <span>{'event': 'uiArchivedCountChanged'}
</span><span>);</span>
Nach dem Login kopieren

Mission erfüllt. Unsere Zähler wissen nichts über unsere Projektlistenreihen, die nichts über die Formen in ihnen wissen. Und keiner der Komponenten ist im geringsten auf das Konzept einer Liste von Projekten entwickelt.

Last -Minute -Addition

Unser UX -Designer hat darauf hingewiesen, dass es besser wäre, wenn wir um Bestätigung fragen, wenn jemand versucht, einen Entwurf zu löschen, da diese Aktion nicht rückgängig gemacht werden kann. Kein Problem, wir können eine Komponente aufschlagen, die genau das tut:
<span>define(function(require) {
</span>  <span>'use strict';
</span>
  <span>var defineComponent = require('flight/lib/component');
</span>
  <span>function <span>Removable</span>() {
</span>    <span>this.defaultAttrs({
</span>      <span>'removeOn': 'uiFormProcessed',
</span>      <span>'broadcastEvents': [
</span>        <span>{'event': 'uiRemoved', 'data': {}}
</span>      <span>]
</span>    <span>});
</span>
    <span>this.after('initialize', function() {
</span>      <span>this.on(this.attr.removeOn, this.remove.bind(this));
</span>    <span>});
</span>
    <span>this.remove = function(event) {
</span>      <span>// Broadcast events to notify the rest of the UI that this component has been removed
</span>      <span>this.attr.broadcastEvents.forEach(function(eventObj) {
</span>        <span>this.trigger(eventObj.event, eventObj.data);
</span>      <span>}.bind(this));
</span>
      <span>// Animate row removal, remove DOM node, teardown component
</span>      $<span>.when(this.$node
</span>        <span>.animate({'opacity': 0}, 'fast')
</span>        <span>.slideUp('fast')
</span>      <span>).done(function() {
</span>        <span>this.$node.remove();
</span>      <span>}.bind(this));
</span>    <span>};
</span>  <span>}
</span>
  <span>return defineComponent(Removable);
</span><span>});</span>
Nach dem Login kopieren

Befestigen Sie das an die Löschtasten, und wir haben das, wonach wir gefragt wurden. Im Dialogfeld "Bestätigung" wird die Schaltfläche abgefangen und die Einreichung des Formulars zulassen, wenn der Benutzer "OK" auswählt. Wir mussten unsere asyncForm -Komponente nicht ändern, da wir diese Komponenten komponieren können, ohne uns gegenseitig zu stören. In unserem Produktionscode verwenden wir auch eine SingleSubmit -Komponente für die Aktionstaste, die visuelles Feedback gibt, das das Formular eingereicht hat, und verhindert mehrere Einreichungen.

endgültige Komponenten, Tests und Vorrichtungen

Hoffentlich hat dieser Artikel gezeigt, wie Ihre Projekte davon profitieren können, Schnittstellen in komponierbare Komponenten zu zerlegen. Ein wichtiger Vorteil des Komponentendesigns, das ich nicht abgedeckt habe, ist die einfache isolierte Tests. Hier sind die endgültigen Komponenten zusammen mit ihren Jasmin -Tests und HTML -Testvorstellungen:

  • asyncForm
  • abnehmbar
  • count
  • bestätigen

Wenn Sie Fragen zu dem haben, was ich behandelt habe, fragen Sie bitte Details in den Kommentaren und ich werde mein Bestes tun, um zu helfen.

häufig gestellte Fragen (FAQs) zu Denkenkomponenten

Was sind die Schlüsselkomponenten des effektiven Denkens? Dazu gehören Klarheit, Präzision, Genauigkeit, Relevanz, Tiefe, Breite, Logik, Bedeutung und Fairness. Jede dieser Komponenten spielt eine entscheidende Rolle, um sicherzustellen, dass unser Denkprozess effektiv ist und zu genauen Schlussfolgerungen führt.

Wie kann ich meine Fähigkeiten zum kritischen Denken verbessern? Gewohnheiten wie die Befragung von Annahmen, die Suche nach verschiedenen Perspektiven und das offene für neue Ideen. Es beinhaltet auch die Entwicklung von Fähigkeiten wie Analyse, Interpretation, Inferenz, Bewertung, Erklärung und Selbstregulierung. kritisches Denken. Es geht dar Die Informationen oder Ideen, die wir in Betracht ziehen, stehen in direktem Zusammenhang mit dem Problem oder dem vorliegenden Problem. Es hilft uns, konzentriert zu bleiben und Ablenkungen oder irrelevante Informationen zu vermeiden.

Welche Bedeutung hat die Bedeutung der Tiefe im kritischen Denken? Problem oder Problem, um seine zugrunde liegenden Ursachen oder Implikationen zu verstehen und sie aus mehreren Perspektiven zu untersuchen.

Wie kann ich in meinem Denken Breite entwickeln?

Breite im Denken beinhaltet die Berücksichtigung einer Vielzahl von Perspektiven, Ideen und Informationsquellen. Es erfordert, aufgeschlossen, neugierig und bereit zu sein, neue Ideen oder Gesichtspunkte zu erforschen. und objektiv. Wir müssen alle relevanten Standpunkte und Beweise berücksichtigen und Bevorzugung, Voreingenommenheit oder Vorurteile vermeiden.

Wie zeigt Präzision zum effektiven Denken? Es hilft uns, Unbestimmtheit, Mehrdeutigkeit oder Verwirrung zu vermeiden und unsere Ideen effektiv zu kommunizieren. , Ideen und Schlussfolgerungen sind korrekt, zuverlässig und frei von Fehlern oder Verzerrungen. Es ist entscheidend für die Entscheidung und Urteile.

Wie kann ich die Klarheit meines Denkens verbessern? Einfachheit und Unkomplizierung in unseren Gedanken und Ausdrücken.

Das obige ist der detaillierte Inhalt vonIn Komponenten denken. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage