Der erste
Artikel über
DAP wurde offensichtlich nicht zu meinem Erfolg beim Schreiben: Die überwiegende Mehrheit der Kommentare dazu lautete "Niasilil" und "Niasilil, aber ich verurteile". Und der Preis für
den einzigen konstruktiven Top-Level-Kommentar geht an
OldVitus , um Ratschläge zu erhalten, wie die Dap am Beispiel von TodoMVC demonstriert werden kann, damit es etwas zu vergleichen gibt. Was mache ich in diesem Artikel?
TodoMVC , falls jemand es nicht weiß, ist dies eine solche Standard-UI-
Aufrufwelt , mit der Sie Lösungen für dasselbe Problem - die bedingte "To-Do-Liste" - unter Verwendung verschiedener Frameworks vergleichen können. Die Aufgabe ist bei all ihrer Einfachheit (ihre
Lösung für Dap Breaks "in einem Bildschirm") sehr anschaulich. Ich werde daher anhand ihres Beispiels versuchen zu zeigen, wie die für ein Web-Frontend typischen Aufgaben mit dap umgesetzt werden.
Ich habe die formale Beschreibung des Problems nicht gesucht und studiert, sondern mich dazu entschlossen, eines der Beispiele einfach umzukehren. Das Backend für diesen Artikel ist für uns nicht interessant, daher schreiben wir es nicht selbst, sondern verwenden
eines der fertigen von der Website
www.todobackend.com . Von dort nehmen wir
einen Beispielclient und eine Standard-
CSS-Datei .
Um dap zu verwenden, müssen Sie nichts herunterladen und installieren. Keine
npm install
und das ist alles. Es ist nicht erforderlich, Projekte mit einer bestimmten Verzeichnisstruktur, Manifesten und anderen Attributen für den IT-Erfolg zu erstellen. Genug Texteditor und Browser. Zum Debuggen von XHR-Anforderungen benötigen Sie möglicherweise auch einen ausreichend einfachen Webserver, z. B. diese
Erweiterung für Chrome. Unser gesamtes Frontend besteht aus einer einzigen .html-Datei (natürlich unter Bezugnahme auf das DAP-Engine-Skript und die Standard-TodoMVC-CSS-Datei).
Also von Grund auf neu.
1. Erstellen Sie eine HTML-Datei
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo -- dap sample</title> <link rel="stylesheet" href="https://www.todobackend.com/client/css/vendor/todomvc-common.css"/> <script src="https://dap.js.org/0.4.js"></script> </head> <body> <script> </script> </body> </html>
Die übliche HTML-Vorbereitung, in der wir die CSS-Datei, die freundlicherweise von der Site
www.todobackend.com bereitgestellt wird, und die DAP-Engine, die ebenfalls freundlicherweise von der Site
dap.js.org bereitgestellt wird,
enthalten2. Kopieren Sie die DOM-Struktur des ursprünglichen Beispiels
Um die Standard-CSS-Datei unverändert zu verwenden, wird dieselbe DOM-Struktur wie im
ursprünglichen Beispiel verwendet . Öffnen Sie es im Chrome-Browser, drücken Sie Strg + Umschalt + I, wählen Sie die Registerkarte "Elemente" und stellen Sie sicher, dass sich die Anwendung selbst im Elementabschnitt
section id="todo-app">

Indem wir diesen Teilbaum einzeln öffnen, schreiben wir seine Struktur in unsere .html-Datei. Jetzt skizzieren wir einfach auf schnelle Weise und schreiben keinen Code. Deshalb schreiben wir die Signaturen der Elemente einfach in einfache Anführungszeichen und in Klammern ihrer Kinder. Wenn es keine Kinder gibt, zeichnen wir leere Klammern. Wir überwachen die Indizes und das Gleichgewicht der Klammern.
Hinweis: Wenn Sie Elemente wiederholen (hier sind es beispielsweise
LI
Elemente), schreiben Sie einmal in die Struktur, auch wenn das Original mehrere Elemente enthält. Offensichtlich sind dies Arrays aus dem gleichen Muster.
Ich denke, das Signaturformat ist für jeden verständlich, der HTML und CSS mit den Händen geschrieben hat, daher werde ich mich im Moment nicht näher damit befassen. Ich kann nur sagen, dass Tags in GROSSBUCHSTABEN geschrieben sind und das Fehlen eines Tags dem Vorhandensein eines DIV-Tags entspricht. Die Fülle von # -Elementen (mit id) ist hier auf die Besonderheiten der enthaltenen CSS-Datei zurückzuführen, die hauptsächlich id-Selektoren verwendet.
3. Denken Sie daran, dass das DAP-Programm Javascript ist
Um uns unnötige Klammern im Code zu ersparen,
String.prototype
Engine mehrere Methoden direkt in
String.prototype
(mir ist bewusst, dass die Implementierung Ihrer Methoden in Standardobjekten ein Problem ist, aber ... kurz gesagt, wir haben es bestanden), das die Signaturzeichenfolge in DAP konvertiert vorlage. Eine solche Methode ist
.d(rule, ...children)
. Das erste Argument, das es braucht, ist eine Generierungsregel (
d-Regel ), und der Rest der Argumente ist eine willkürliche Anzahl von untergeordneten Elementen.
Basierend auf diesem neuen Wissen fügen wir unseren Code so hinzu, dass wir anstelle jeder öffnenden Klammer die Sequenz
.d(""
haben und vor jedem öffnenden einfachen Anführungszeichen, mit Ausnahme des allerersten, ein Komma steht. Life Hack: Sie können die automatische Ersetzung verwenden.
'#todoapp'.d("" ,'#header'.d("" ,'H1'.d("") ,'INPUT#new-todo placeholder="What needs to be done?" autofocus'.d("") ) ,'#main'.d("" ,'#toggle-all type=checkbox'.d("") ,'UL#todo-list'.d("" ,'LI'.d("" ,'INPUT.toggle type=checkbox'.d("") ,'LABEL'.d("") ,'BUTTON.destroy'.d("") ) ) ) ,'#footer'.d("" ,'#todo-count'.d("") ,'UL#filters'.d("" ,'LI'.d("") ) ,'#clear-completed'.d("") ) )
Voila! Wir haben eine
.d
von Aufrufen für die
.d
Methode erhalten, die in eine DAP-Vorlage umgewandelt werden kann. Die leeren Zeichenfolgen
""
sind die Keime zukünftiger D-Regeln, und die untergeordneten Zeichen sind durch Kommas getrennte Argumente. Formal ist dies ein gültiges DAP-Programm, wenn auch noch nicht vollständig mit dem Auspuff, den wir brauchen. Aber es kann schon gestartet werden!
.RENDER()
Sie dazu nach der schließenden
.RENDER()
die
.RENDER()
Methode hinzu. Diese Methode rendert, wie der Name schon sagt, die resultierende Vorlage.
Zu diesem Zeitpunkt liegt also eine HTML-Datei mit folgendem Inhalt vor:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo -- dap sample</title> <link rel="stylesheet" href="https://www.todobackend.com/client/css/vendor/todomvc-common.css"/> <script src="https://dap.js.org/0.4.js"></script> </head> <body> <script> '#todoapp'.d("" ,'#header'.d("" ,'H1'.d("") ,'INPUT#new-todo placeholder="What needs to be done?" autofocus'.d("") ) ,'#main'.d("" ,'#toggle-all type=checkbox'.d("") ,'UL#todo-list'.d("" ,'LI'.d("" ,'INPUT.toggle type=checkbox'.d("") ,'LABEL'.d("") ,'BUTTON.destroy'.d("") ) ) ) ,'#footer'.d("" ,'#todo-count'.d("") ,'UL#filters'.d("" ,'LI'.d("") ) ,'#clear-completed'.d("") ) ) .RENDER() // dap </script> </body> </html>
Sie können
es in einem Browser öffnen , um sicherzustellen, dass DOM-Elemente generiert und CSS-Stile angewendet werden. Sie müssen diese Vorlage nur noch mit Daten füllen.
4. Holen Sie sich die Daten
Wir gehen zur
Originalseite , öffnen die Registerkarte Netzwerk in den Tools, aktivieren den XHR-Filter und sehen, woher die Daten kommen und in welcher Form.


Okay, okay. Die
Aufgabenliste wird direkt von
todo-backend-express.herokuapp.com als
JSON- Array von Objekten übernommen. Großartig
Um Daten zu empfangen, verfügt dap über einen eingebauten Konverter
:query
der die URL asynchron in die von ihm empfangenen Daten "konvertiert". Wir werden die URL selbst nicht direkt in die Regel schreiben, sondern sie mit den konstanten
todos
. Dann sieht das gesamte Data Mining-Design folgendermaßen aus:
todos:query
und schreiben Sie die
todos
Konstante selbst in das Wörterbuch - im Abschnitt
.DICT
direkt vor
.RENDER()
:
'#todoapp'.d("" ... ) .DICT({ todos : "https://todo-backend-express.herokuapp.com/" }) .RENDER()
Nachdem wir das Array
todos
, erstellen wir daraus eine
.title
-Do-Liste: Für jeden Fall nehmen wir den Namen aus dem Feld
.title
und schreiben ihn in das Element
LABEL
, und aus dem Feld
.completed
nehmen
.completed
das Vorzeichen für „Vollständigkeit“ und schreiben in die Eigenschaft
checked
des
checked
INPUT.toggle
. Es ist so gemacht:
,'UL#todo-list'.d("*@ todos:query"
Wir aktualisieren unsere Seite im Browser und ... wenn Sie sie vom Dateisystem aus starten, passiert nichts. Das Problem ist, dass moderne Browser keine domänenübergreifenden XHR-Anforderungen aus lokalen Dokumenten zulassen.

Es ist Zeit, unsere Seite über http anzuschauen - mit einem beliebigen lokalen Webserver. Nun, oder wenn Sie nicht bereit sind, DAP mit Ihren eigenen Händen zu schreiben, sehen Sie sich die aufeinander folgenden Versionen der Seite unter Verwendung meiner Links an (vergessen Sie nicht, den Quellcode zu betrachten - in Chrome geschieht dies mit Strg + U).
Also
gehen wir
zu unserer Seite unter http: // und sehen, dass die Daten kommen und die Liste erstellt wird. Großartig! Sie haben die Operatoren
*
und bereits gemeistert
!
, converter
:query
, Konstanten und Zugriff auf die Felder des aktuellen Array-Elements. Schauen Sie sich den resultierenden Code noch einmal an. Scheint es Ihnen immer noch unlesbar?
5. Zustand hinzufügen
Möglicherweise haben Sie bereits versucht, auf die Häkchen in der Aufgabenliste zu klicken. Die Kontrollkästchen selbst ändern die Farbe, aber im Gegensatz zum Original ändert das übergeordnete
LI
Element seinen Stil nicht (der „erledigte Auftrag“ sollte grau und durchgestrichen sein, dies geschieht jedoch nicht) - die Dinge ändern ihren
Status nicht . Diese Elemente haben jedoch noch keinen Status und können ihn dementsprechend nicht ändern. Jetzt werden wir es reparieren.
Fügen Sie dem
LI
Element den Status "Abgeschlossen" hinzu. Definieren Sie dazu in seiner D-Regel die
Variable $completed
state . Dem
INPUT.toggle
, das diesen Status ändern kann, wird eine entsprechende Reaktionsregel (
ui-rule ) zugewiesen, mit der die Variable
$completed
entsprechend ihrem eigenen aktivierten Flag gesetzt wird ("daw ist eingeschaltet"). Abhängig vom Status von
$completed
aktiviert oder deaktiviert das
LI
Element die CSS-Klasse "completed".
,'UL#todo-list'.d("*@ todos:query" ,'LI'.d("$completed=.completed"
Solche Manipulationen mit CSS-Klassen sind ziemlich verbreitet, es gibt also einen speziellen Operator in dap für sie !?
Bitte beachten Sie, dass wir dies in der
Regel tun (ab dem Wort akkumulieren). Warum nicht in der D-Regel? Der Unterschied zwischen diesen beiden Regeltypen besteht darin, dass die d-Regel beim Aktualisieren den Inhalt des Elements vollständig neu erstellt und dabei den alten und den neuen Inhalt wieder löscht, während die a-Regel den vorhandenen Inhalt des Elements nicht berührt, sondern das Ergebnis an das anfügt, was bereits vorhanden ist. Das Ändern eines einzelnen Attributs eines
LI
Elements erfordert keine Umstrukturierung des restlichen Inhalts. Daher ist es rationaler, dies in der Regel zu tun.
Wir schauen uns das
Ergebnis an . Es ist schon besser: Wenn Sie auf die Kontrollkästchen klicken, ändert sich der Status des entsprechenden Aufgabenelements, und entsprechend ändert sich auch der visuelle Stil des Elements. Es besteht jedoch weiterhin ein Problem: Wenn die Liste der abgeschlossenen Aufgaben ursprünglich vorhanden war, werden sie nicht grau angezeigt, da die a-Regel standardmäßig nicht ausgeführt wird, wenn das Element generiert wird. Um es auch während der Generierung auszuführen, fügen wir den Operator
a!
Zur d-Regel des Elements
LI
,'LI'.d("$completed=.completed; a!"
Wir schauen Ok Mit dem Status von
$completed
herausgefunden. Abgeschlossene Fälle werden sowohl beim ersten Systemstart als auch beim anschließenden manuellen Umschalten korrekt stilisiert.
6. Bearbeiten von Fallnamen
Zurück zum
Original . Durch Doppelklick auf den Namen des Falls wird der Bearbeitungsmodus aktiviert, in dem dieser Name geändert werden kann. Dort wird es so implementiert, dass die Ansichtsmodusvorlage „Ansicht“ (mit einer Morgendämmerung, einem Titel und einer Löschschaltfläche) vollständig ausgeblendet wird und das Element
INPUT class="edit"
angezeigt wird. Wir werden es etwas anders machen - wir werden nur das
LABEL
Element verbergen, da die anderen beiden Elemente unsere Bearbeitung nicht stören.
LABEL
einfach die
view
zum
LABEL
Element hinzu.
Definieren Sie für den Status "Bearbeitung" die Variable "
$editing
im
LI
Element. Anfangs wird es (Zustand) zurückgesetzt, durch
dblclick
auf das
LABEL
Element
LABEL
und
LABEL
, wenn das
INPUT.edit
Element nicht mehr im Fokus steht. Also schreiben wir:
,'LI'.d("$completed=.completed $editing=; a!"
Jetzt können wir die Namen der Fälle bearbeiten.
7. Senden von Daten an den Server
Ok, wir können bereits Dinge im Browser bearbeiten, aber diese Änderungen müssen auch auf den Server übertragen werden. Wir schauen, wie das Original es macht:

Die Änderungen werden mithilfe der PATCH-Methode mit einer bestimmten URL in der Form
http://todo-backend-express.herokuapp.com/28185
an den Server gesendet, die natürlich für jeden Fall eindeutig ist. Diese URL wird vom Server im Feld
.url
für jeden Fall in der Liste angegeben. Das heißt, wir müssen lediglich eine PATCH-Anforderung an die im Feld
.url
angegebene Adresse
.url
, und zwar mit den geänderten Daten im JSON-Format:
,'INPUT.edit' .d("? $editing; !! .title@value") .ui(".title=#.value; (@method`PATCH .url (@Content-type`application/json)@headers (.title):json.encode@body):query") .e("blur","$editing=")
Hier verwenden wir den gleichen Konverter
:query
, jedoch in einer detaillierteren Version. Wenn
:query
auf eine einfache Zeichenfolge angewendet wird, wird diese Zeichenfolge als URL behandelt und eine GET-Anforderung ausgeführt. Wenn
:query
ein komplexes Objekt empfängt, wie in diesem Fall, wird es als detaillierte Beschreibung der Anfrage mit den Feldern
.method
,
.url
,
.headers
und
.body
und die Anfrage entsprechend ausgeführt. Hier senden
.title
unmittelbar nach der Aktualisierung von
.title
eine PATCH-Anfrage mit diesem aktualisierten
.title
den Server
Aber es gibt eine Nuance. Wir bekommen das
.url
Feld vom Server, es sieht
.url
aus:
http://todo-backend-express.herokuapp.com/28185
,
.url
das http: // -Protokoll ist darin fest codiert, wenn unser Client auch über http: // geöffnet ist dann ist alles in ordnung. Wenn der Client jedoch über https: // geöffnet ist, tritt ein Problem auf: Aus Sicherheitsgründen blockiert der Browser den http-Verkehr von der https-Quelle.
Es ist einfach gelöst: Wenn Sie das Protokoll aus
.url
entfernen,
.url
die Anforderung das
.url
. Also lasst es uns tun: Schreiben Sie den entsprechenden Konverter -
dehttp
, und wir werden
.url
durchlaufen. Benutzerdefinierte Konverter (und andere Funktionen) werden im Abschnitt
.FUNC
:
.ui(".title=#.value; (@method`PATCH .url:dehttp (@Content-type`application/json)@headers (.title):json.encode@body):query") ... .FUNC({ convert:{
Es ist auch sinnvoll, das Header-Objekt in das Wörterbuch einzufügen, damit es in anderen Abfragen verwendet werden kann:
.ui(".title=#.value; (@method`PATCH .url:dehttp headers (.title):json.encode@body):query") ... .DICT({ todos : "//todo-backend-express.herokuapp.com/", headers: {"Content-type":"application/json"} })
Nun, für Full Feng Shui werden wir eine andere nützliche Eigenschaft des Konverters verwenden
:query
- automatische Codierung des Anforderungskörpers in json gemäß dem
Content-type:application/json
Header. Infolgedessen sieht die Regel folgendermaßen aus:
.ui(".title=#.value; (@method`PATCH .url:dehttp headers (.title)):query")
Also
schau . Okay, Fallnamen ändern sich jetzt nicht nur im Browser, sondern auch auf dem Server. Aber! Es kann sich nicht nur der Name des Falls ändern, sondern auch sein Fertigstellungsgrad -
completed
. Es muss also auch an den Server gesendet werden.
Sie können dieselbe PATCH-Anfrage zum
INPUT.toggle
Element hinzufügen. Senden
INPUT.toggle
einfach
(.completed)
anstelle von
(.completed)
:
,'INPUT.toggle type=checkbox' .d("#.checked=.completed") .ui("$completed=#.checked; (@method`PATCH .url:dehttp headers (.completed:?)):query")
Und Sie können diese PATCH-Anfrage "aus Klammern" setzen:
,'LI'.d("$completed=.completed $editing= $patch=; a!"
Hier ist das Ding. Reaktionsregeln gehören zur Gruppe der „Aufwärtsregeln“, die „von unten nach oben“ ausgeführt werden - vom Nachkommen zum übergeordneten Element bis zur Wurzel selbst (diese Sequenz kann bei Bedarf unterbrochen werden). Dies ähnelt Popup-Ereignissen im DOM. Daher können einige Fragmente der Reaktion, die mehreren Nachkommen gemeinsam sind, einem gemeinsamen Vorfahren zugeordnet werden.
Insbesondere ist in unserem Fall der Vorteil einer solchen Delegierung nicht besonders bemerkbar. Wenn jedoch mehr bearbeitbare Felder vorhanden wären, würde es sehr hilfreich sein, diese umfangreiche Anforderung (natürlich nach DAP-Standards) in eine allgemeine Regel zu packen, um den Code einfach und lesbar zu halten. Also ich empfehle es.
Wir schauen : Nun werden sowohl Namensänderungen als auch Statusänderungen an den Server gesendet.
Wenn Sie im nächsten Artikel interessiert sind, sollten Sie Fälle hinzufügen, entfernen und filtern. In der Zwischenzeit können Sie das
Endergebnis und andere Beispiele für
DAP- Code unter
dap.js.org/docs sehen