Portieren Sie Ihre Webanwendung von reinem JavaScript nach Vue.js.

Vue.js ist ein Framework für die Entwicklung von Webanwendungen. Es verfügt über ein Reaktivitätssystem, mit dem der Entwickler den Status der Anwendung simulieren und verwalten kann. Wenn sich die Daten ändern, werden sie automatisch auf der Benutzeroberfläche angezeigt, während der Entwickler nicht auf das DOM zugreifen muss. Wenn Sie Anwendungen mit reinem JavaScript oder jQuery erstellen, bedeutet dies, dass Sie explizit auf die DOM-Elemente zugreifen und diese aktualisieren müssen, um Änderungen im Status der Anwendung in der Benutzeroberfläche widerzuspiegeln und beispielsweise einige Daten auf einer Webseite anzuzeigen.


Bei großen Projekten ist die manuelle Verwaltung der Synchronisation von Status und Anwendungsschnittstelle keine leichte Aufgabe. Der Autor des Materials, dessen Übersetzung wir Ihnen heute vorstellen, möchte einige Ergebnisse seiner Forschung mitteilen , die darauf abzielt, zwei Versionen einer progressiven Webanwendung mit Hoodie , einer Einkaufsliste, zu vergleichen . Die Basisversion dieser Anwendung ist in reinem JS geschrieben (in diesem Artikel finden Sie Details dazu). Hier wird die Übersetzung der Anwendung in Vue.js mit einer bestandenen Prüfung der Grundfunktionen dieses Frameworks und einer Analyse dessen gezeigt, was am Ende passiert ist.


Bereit für die Bewerbung

Wenn Sie dieses Material durcharbeiten möchten, können Sie den Quellcode der Anwendung in reinem JS herunterladen und dem Autor folgen und ihn mit Vue verarbeiten.

Hinzufügen von Produkten zur Liste


▍JavaScript


Die Anwendung ermöglicht es dem Benutzer, Produkte zu seiner Einkaufsliste hinzuzufügen. Dies erfolgt in der Datei index.html im öffentlichen Ordner. Das Markup ist in den Zeilen 92-124 dieser Datei enthalten. Da ist sie.

 <div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="text" id="new-item-name">     <label class="mdl-textfield__label" for="new-item-name">Item Name</label> </div> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-cost">     <label class="mdl-textfield__label" for="new-item-cost">Item Cost</label> </div> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-quantity">     <label class="mdl-textfield__label" for="new-item-quantity">Quantity</label> </div> </div> <div class="mdl-grid center-items"> <button id="add-item" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">     Add Item </button> </div> </div> 

Der Code zum Verarbeiten und Speichern von Daten befindet sich in der Datei public/js/src/index.js . Die Funktion saveItems() in Zeile 28 ist dafür verantwortlich, die Werte von den Steuerelementen zu erfassen, die zur Dateneingabe verwendet werden, und diese Daten zu speichern. Diese Funktion ist an das click der Schaltfläche " add-item gebunden. Hier ist der fragliche Code.

 function saveNewitem() { let name = document.getElementById("new-item-name").value; let cost = document.getElementById("new-item-cost").value; let quantity = document.getElementById("new-item-quantity").value; let subTotal = cost * quantity; if (name && cost && quantity) {   hoodie.store.withIdPrefix("item").add({     name: name,     cost: cost,     quantity: quantity,     subTotal: subTotal   });   document.getElementById("new-item-name").value = "";   document.getElementById("new-item-cost").value = "";   document.getElementById("new-item-quantity").value = ""; } else {   let snackbarContainer = document.querySelector("#toast");   snackbarContainer.MaterialSnackbar.showSnackbar({     message: "All fields are required"   }); } } document.getElementById("add-item").addEventListener("click", saveNewitem); 

UeVue


Bevor Sie dieses Projekt mit Vue überarbeiten können, müssen Sie das Framework mit der Seite verbinden. In unserem Fall geschieht dies in der Datei index.html wie folgt:

 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 

Darüber hinaus wurde mit der Bezeichner- app ein <div> -Element hinzugefügt, das alle Seitenelemente enthält, die sich innerhalb des body Tags befinden. Dies liegt daran, dass das Framework bei der Initialisierung der Vue-Instanz darüber informiert werden muss, welchen Teil der Seite es verwalten soll. In diesem Fall teilen wir dem Framework mit, dass es sich mit allem befassen soll, was sich in diesem Block befindet.

Beginnen wir nun mit der Übersetzung des Projekts in Vue. Zuerst ändern wir das Markup, um einige Vue-Anweisungen zu verwenden. Vue-Direktiven sind spezielle Attribute, denen v- vorangestellt ist. So sieht das aktualisierte Markup aus.

 <form v-on:submit.prevent="onSubmit"> <div class="mdl-grid center-items">   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="text" id="new-item-name" v-model="name">     <label class="mdl-textfield__label" for="new-item-name">Item Name</label>   </div>   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-cost" v-model.number="cost">     <label class="mdl-textfield__label" for="new-item-cost">Item Cost</label>   </div>   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-quantity" v-model.number="quantity">     <label class="mdl-textfield__label" for="new-item-quantity">Quantity</label>   </div> </div> <div class="mdl-grid center-items">   <button id="add-item" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">     Add Item   </button> </div> </form> 

Die hier verwendete v-on Direktive wird verwendet, um auf DOM-Ereignisse zu warten. Im obigen Code-Snippet wird es im Formularelement verwendet, um auf das submit Ereignis zu submit . Darüber hinaus wird der Modifikator .prevent , der die v-on Direktive event.preventDefault() , event.preventDefault() für das aufgerufene Ereignis event.preventDefault() . Wir haben die v-model Direktive für Elemente verwendet, die für die Dateneingabe verwendet werden. In Form von Elementen ist es erforderlich, eine bidirektionale Datenbindung zu erstellen. Auf diese Weise kann das System automatisch die richtige Methode zum Aktualisieren eines Elements basierend auf seinem Typ auswählen. Wir haben den Modifikator .number für die cost und quantity verwendet.

Dadurch wird der Werttyp automatisch aus dem Eingabefeld in eine Zahl konvertiert. Dies geschieht, weil der Wert immer als Zeichenfolge zurückgegeben wird, selbst wenn der Typ auf type=number ist. Die hier verwendeten Modifikatoren automatisieren die Ausführung zusätzlicher Prüfungen, die zuvor unabhängig durchgeführt werden mussten.

Erstellen Sie als Nächstes eine neue Datei, index-vue.js , in der wir den Code platzieren, der dem in index.js , aber die Funktionen von Vue verwenden. Der Code für diese Datei wird unten angezeigt. Dadurch wird eine Instanz von Vue mit den erforderlichen Eigenschaften zum Verarbeiten von Formularereignissen und zum Sammeln von Daten erstellt.

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "" }, methods: {   onSubmit: function(event) {     if (this.name && this.cost && this.quantity) {       hoodie.store.withIdPrefix("item").add({         name: this.name,         cost: this.cost,         quantity: this.quantity,         subTotal: this.cost * this.quantity       });       this.name = "";       this.cost = "";       this.quantity = "";     } else {       const snackbarContainer = document.querySelector("#toast");       snackbarContainer.MaterialSnackbar.showSnackbar({         message: "All fields are required"       });     }   } } }); 

In diesem Codefragment wurde eine Instanz von Vue erstellt und ein Objekt an dieses übergeben, das Vue mitteilt, wie die Anwendung konfiguriert werden soll. Die Eigenschaft el teilt dem Framework die Kennung des DOM-Elements mit, dessen Inhalt von Vue gesteuert wird, wobei es als sein "Territorium" betrachtet wird. Innerhalb dieses Elements berücksichtigt Vue die Framework-spezifischen Anweisungen (und alles andere, was mit Vue zusammenhängt) und konfiguriert bei der Initialisierung des Frameworks die Bindungen und Ereignishandler für die Anwendung.

Die data enthält den Status der Anwendung. Alle Eigenschaften des hier verfügbaren Objekts werden beim Initialisieren von Vue dem Reaktionssystem des Frameworks hinzugefügt. Es sind die Aktionen dieses Systems, die zur Aktualisierung der Benutzeroberfläche führen, wenn mit dem DOM verknüpfte Werte geändert werden. Beispielsweise wird die Eigenschaft name mithilfe der Anweisung v-model="name" an das name gebunden. Diese Anweisung legt die bidirektionale Datenbindung zwischen der Eigenschaft und dem Steuerelement so fest, dass die Eigenschaft name aktualisiert wird, wenn dem Eingabefeld etwas hinzugefügt (oder etwas daraus entfernt) wird. Infolgedessen spiegelt der Inhalt des Eingabefelds den aktuellen Status der Eigenschaft name wider.

Ebenso funktioniert das Binden mit anderen Steuerelementen.

Die methods properties enthält Funktionen. Im obigen Code ist die Funktion onSubmit() , die an das submit() onSubmit() angehängt ist.

Anzeigen gespeicherter Daten auf einer Seite


▍JavaScript


Die onSubmit Funktion speichert Daten in einem Hoodie. Danach müssen wir die dem Repository hinzugefügten Elemente in Form einer Tabelle anzeigen. Bei einer Anwendung, die in regulärem JS geschrieben ist, sieht das entsprechende Markup folgendermaßen aus:

 <div class="mdl-grid center-items"> <table id="item-table" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">   <thead>     <tr>       <th class="mdl-data-table__cell--non-numeric">Item Name</th>       <th class="mdl-data-table__cell--non-numeric">Cost</th>       <th class="mdl-data-table__cell--non-numeric">Quantity</th>       <th class="mdl-data-table__cell">Sub-total</th>       <th class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon">           <i class="material-icons">delete</font></i>         </button>       </th>     </tr>   </thead>   <tbody>   </tbody> </table> </div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">   <input class="mdl-textfield__input" type="number" id="total-cost" readonly value="0">   <label class="mdl-textfield__label" for="cost">Total Item Cost</label> </div> </div> <script id="item-row" type="text/template"> <tr id='{{row-id}}'>        <td class="mdl-data-table__cell--non-numeric">{{name}}</td>   <td class="mdl-data-table__cell--non-numeric">{{cost}}</td>   <td class="mdl-data-table__cell--non-numeric">{{quantity}}</td>   <td class="mdl-data-table__cell">{{subTotal}}</td>   <td class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored"         onclick="pageEvents.deleteItem('{{item-id}}')">         <i class="material-icons">remove</font></i>         </button>   </td> </tr> </script> 

Die Tabelle enthält dynamisch hinzugefügte Daten. Daher müssen wir hier die Platzhalter durch echte Daten ersetzen und anhängen, was mit dem DOM geschehen ist. In unserem Fall wird dieses Problem mithilfe von Mikrovorlagen gelöst.

Der folgende Code zeigt die Elemente in der Benutzeroberfläche, wenn sie hinzugefügt werden.

 function addItemToPage(item) { if (document.getElementById(item._id)) return; let template = document.querySelector("#item-row").innerHTML; template = template.replace("{{name}}", item.name); template = template.replace("{{cost}}", item.cost); template = template.replace("{{quantity}}", item.quantity); template = template.replace("{{subTotal}}", item.subTotal); template = template.replace("{{row-id}}", item._id); template = template.replace("{{item-id}}", item._id); document.getElementById("item-table").tBodies[0].innerHTML += template; let totalCost = Number.parseFloat(   document.getElementById("total-cost").value ); document.getElementById("total-cost").value = totalCost + item.subTotal; } hoodie.store.withIdPrefix("item").on("add", addItemToPage); 

In diesem Codefragment wird die Vorlage aus dem DOM abgerufen, die Platzhalter werden durch reale Daten ersetzt und das Ergebnis wird an das DOM angehängt. Anschließend wird der total-cost berechnet, der Gesamtbetrag für alle Elemente der Liste, der auch in der Benutzeroberfläche angezeigt wird.

UeVue


Beim Wechsel zu Vue wurde die vom Skript verwendete Vorlage gelöscht und die Tabellenelemente wurden neu gestaltet, sodass sie die Vue v-for Direktive verwendeten, mit der Sie eine Eigenschaft durchlaufen können, die die Daten der Elemente enthält. So sieht nun das entsprechende Markup aus.

 <div class="mdl-grid center-items"> <table id="item-table" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">   <thead>     <tr>       <th class="mdl-data-table__cell--non-numeric">Item Name</th>       <th class="mdl-data-table__cell--non-numeric">Cost</th>       <th class="mdl-data-table__cell--non-numeric">Quantity</th>       <th class="mdl-data-table__cell">Sub-total</th>       <th class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon">           <i class="material-icons">delete</font></i>         </button>       </th>     </tr>   </thead>   <tbody>     <tr v-for="item in items" :key="item._id">       <td class="mdl-data-table__cell--non-numeric">{{ item.name}}</td>       <td class="mdl-data-table__cell--non-numeric">{{ item.cost}}</td>       <td class="mdl-data-table__cell--non-numeric">{{ item.quantity}}</td>       <td class="mdl-data-table__cell">{{ item.subTotal}}</td>       <td class="mdl-data-table__cell--non-numeric">         <button @click="deleteRow(item._id)" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">           <i class="material-icons">remove</font></i>         </button>       </td>     </tr>   </tbody> </table> </div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">   <!-- <input class="mdl-textfield__input" type="number" id="total-cost" readonly value="0">   <label class="mdl-textfield__label" for="cost">Total Item Cost</label> -->   <h4>Total Cost: {{ total }}</h4> </div> </div> 

Tatsächlich wurden keine so großen Änderungen am Markup vorgenommen. Hier wird der Inhalt der zuvor verwendeten Mikrovorlage kopiert und die Anweisungen und Interpolationsmechanismen des Vue-Textes verwendet. Die v-for Direktive wird verwendet, um die Elemente aufzulisten, deren Daten aus der Eigenschaft items . Daten werden mithilfe der Funktionen des Vue-Konstrukts {{ item.name }} in Spalten angezeigt. Dieser Mechanismus ähnelt den in der Mikrovorlage verwendeten Platzhaltern. Der Gesamtbetrag wird auch mithilfe der Textinterpolationstechnologie auf der Seite angezeigt.

Jetzt werden wir den JavaScript-Code in der index-vue.js und Folgendes erhalten.

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "",   items: [] }, computed: {   //     total: function() {     // `this`    vm     return this.items.reduce(       (accumulator, currentValue) => accumulator + currentValue.subTotal,       0     );   } }, methods: {   ..... } }); hoodie.store.withIdPrefix("item").on("add", item => vm.items.push(item)); 

Eine von Vue vorbereitete Variante des beschriebenen Mechanismus erwies sich als viel kürzer und einfacher als die mit regulärem JS erstellte. In diesem Code wurde die Eigenschaft items data hinzugefügt, die in der oben genannten v-for Direktive verwendet wird. Wenn ein Element hinzugefügt wird, ruft der Hoodie eine Funktion auf, die die Operation vm.items.push(item) ausführt, um den Status der Anwendung zu aktualisieren. Dank des Vue-Reaktivitätssystems wird die Benutzeroberfläche automatisch aktualisiert. Um den Gesamtbetrag zu berechnen, müssen Sie nicht auf die DOM-Elemente verweisen. Hier verwenden wir eine berechnete Eigenschaft, die den .reduce() mit der Funktion .reduce() . Dank des Vue-Reaktivitätssystems wird die Benutzeroberfläche jetzt aktualisiert, wenn sich diese Werte ändern. Das Gute ist, dass der Programmierer sich so keine Gedanken über die Arbeit mit DOM-Elementen im Code machen muss. Infolgedessen haben wir mit Hilfe von kleinerem Code das gleiche Problem gelöst, das im Fall von regulärem JS viel mehr Code erforderte (wenn in dieser Situation anstelle von gewöhnlichem JS die jQuery-Bibliothek verwendet würde, würde die Katze auch eine größere Größe haben. als die, die Sie bei der Verwendung von Vue erhalten haben).

Elemente als Liste speichern


▍JavaScript


Nach dem Hinzufügen von Elementen müssen Sie diese für die spätere Verwendung speichern, damit Sie später weitere Systemlisten zum System hinzufügen können. Die Anwendung verfügt über eine Schaltfläche " Save List , die für das Sammeln von Daten, das Speichern als Gruppe von Elementen mithilfe von Hoodie-Tools und das Hinzufügen neuer Elemente zum System durch den Benutzer verantwortlich ist.

Bei Verwendung von onClick JavaScript ist die entsprechende Funktion an das onClick button gebunden. Hier ist das Markup.

 //index.html <div class="mdl-grid center-items"> <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" onclick="pageEvents.saveList()">   Save List </button> </div> 

Hier ist der Funktionscode.

 //index.js function saveList() { let cost = 0; hoodie.store   .withIdPrefix("item")   .findAll()   .then(function(items) {     for (var item of items) {       cost += item.subTotal;     }     //      hoodie.store.withIdPrefix("list").add({       cost: cost,       items: items     });     //      hoodie.store       .withIdPrefix("item")       .remove(items)       .then(function() {         //          document.getElementById("item-table").tBodies[0].innerHTML = "";         //          var snackbarContainer = document.querySelector("#toast");         snackbarContainer.MaterialSnackbar.showSnackbar({           message: "List saved succesfully"         });       })       .catch(function(error) {         //             var snackbarContainer = document.querySelector("#toast");         snackbarContainer.MaterialSnackbar.showSnackbar({           message: error.message         });       });   }); } window.pageEvents = { deleteItem: deleteItem, saveList: saveList .... }; 

UeVue


Der Wechsel zu Vue erfordert keine großen Änderungen. Wir müssen den Handler weiterhin an das Ereignis binden, das beim Klicken auf die Schaltfläche ausgelöst wird. Außerdem müssen wir die Methode, die der Handler dieses Ereignisses ist, bei der Initialisierung der Methodeigenschaft des Vue-Objekts hinzufügen.

So sieht das Markup jetzt aus.

 <div class="mdl-grid center-items"> <button @click="saveList" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">   Save List </button> </div> 

Das @click="saveList" ist eine Abkürzung für v-on:click="saveList" . Dieser Mechanismus wird verwendet, um auf DOM-Ereignisse zu warten. Die saveList , die in der in reinem JS geschriebenen Anwendungsversion verwendet wurde, wird der saveList des Vue-Objekts hinzugefügt.

Navigationsleiste


▍JavaScript


Nachdem die Elemente als Liste gespeichert werden können, möchten wir zuvor gespeicherte Listen mit Daten zum Gesamtwert der darin enthaltenen Waren anzeigen können. Diese Informationen werden auf einer anderen Seite angezeigt. Sie sehen wie die unten gezeigte aus.


Daten zu zuvor erstellten Produktlisten

Das Markup für diese Seite befindet sich in der Datei public/history.html , der entsprechende JS-Code befindet sich in der Datei public/js/src/history.js . Diese Seite und index.html haben etwas gemeinsam. Dies ist eine Navigationsleiste oben im Fenster. Dieses Fenster enthält Links zu verschiedenen Seiten, Login und Register , die Dialogformulare zum Aufrufen des Systems und zum Registrieren aufrufen. Es gibt auch eine Signout zum Abmelden.
In der Version der Anwendung, die mit normalem JS erstellt wurde, mussten Sie auf beiden Seiten dasselbe Markup duplizieren. So sieht der HTML-Code der Navigationsleiste aus.

 <header class="mdl-layout__header">   <div class="mdl-layout__header-row">   <!-- Title -->   <span class="mdl-layout-title">Shopping List</span>   <!-- Add spacer, to align navigation to the right -->   <div class="mdl-layout-spacer"></div>   <!-- Navigation. We hide it in small screens. -->   <nav class="mdl-navigation mdl-layout--large-screen-only">       <a class="mdl-navigation__link" href="index.html">Home</a>       <a class="mdl-navigation__link" href="history.html">History</a>       <a onclick="pageEvents.showLogin()" style="cursor: pointer" class="mdl-navigation__link login">Login</a>       <a onclick="pageEvents.showRegister()" style="cursor: pointer" class="mdl-navigation__link register">Register</a>       <a onclick="pageEvents.signout()" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>   </nav>   </div> </header> <div class="mdl-layout__drawer">   <span class="mdl-layout-title">Shopping List</span>   <nav class="mdl-navigation">   <a class="mdl-navigation__link" href="index.html">Home</a>   <a class="mdl-navigation__link" href="history.html">History</a>   <a onclick="pageEvents.showLogin()" style="cursor: pointer" class="mdl-navigation__link login">Login</a>   <a onclick="pageEvents.showRegister()" style="cursor: pointer" class="mdl-navigation__link register">Register</a>   <a onclick="pageEvents.signout()" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>   </nav> </div> 

Nach der Analyse dieses Codes werden Sie feststellen, dass beim Klicken auf die Links Login , Register und Logout die entsprechenden Funktionen aufgerufen werden. Ereignishandler für die in diesem Markup beschriebenen Elemente sind in der Datei index.js definiert.

 import * as shared from "shared.js"; .... shared.updateDOMLoginStatus(); window.pageEvents = { showLogin: shared.showLoginDialog, showRegister: shared.showRegisterDialog, signout: shared.signOut }; 

Die Funktionen, die für die Arbeit mit der Navigationsleiste verantwortlich sind, sind in der Datei shared.js deklariert.

 //   let loginDialog = document.querySelector("#login-dialog"); dialogPolyfill.registerDialog(loginDialog); let registerDialog = document.querySelector("#register-dialog"); dialogPolyfill.registerDialog(registerDialog); let showLoginDialog = function() { loginDialog.showModal(); }; let showRegisterDialog = function() { registerDialog.showModal(); }; let showAnonymous = function() { document.getElementsByClassName("login")[0].style.display = "inline"; document.getElementsByClassName("login")[1].style.display = "inline"; document.getElementsByClassName("register")[0].style.display = "inline"; document.getElementsByClassName("register")[1].style.display = "inline"; document.getElementsByClassName("logout")[0].style.display = "none"; document.getElementsByClassName("logout")[1].style.display = "none"; }; let showLoggedIn = function() { document.getElementsByClassName("login")[0].style.display = "none"; document.getElementsByClassName("login")[1].style.display = "none"; document.getElementsByClassName("register")[0].style.display = "none"; document.getElementsByClassName("register")[1].style.display = "none"; document.getElementsByClassName("logout")[0].style.display = "inline"; document.getElementsByClassName("logout")[1].style.display = "inline"; }; let updateDOMLoginStatus = () => { hoodie.account.get("session").then(function(session) {   if (!session) {     //          showAnonymous();   } else if (session.invalid) {     //   ,          showAnonymous();   } else {     //         showLoggedIn();   } }); }; let signOut = function() { hoodie.account   .signOut()   .then(function() {     showAnonymous();     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "You logged out"     });     location.href = location.origin;   })   .catch(function() {     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "Could not logout"     });   }); }; export { signOut, showRegisterDialog, showLoginDialog, updateDOMLoginStatus }; 

Dieser Code exportiert die Funktionen, die in index.js . Die Funktionen showLoginDialog() und showRegisterDialog() zeigen modale Dialogfelder zum Anmelden und Registrieren an. Mit der Funktion signout() kann sich der Benutzer showAnonymous() und die Funktion showAnonymous() , die den Link showAnonymous() verbirgt und nur die Links Register und showAnonymous() . Die Funktion updateDOMLoginStatus() prüft, ob der Benutzer authentifiziert ist, und zeigt die entsprechenden Links an. Diese Funktion wird beim Laden der Seite aufgerufen.

Um dieselbe Navigationsleiste auf zwei verschiedenen Seiten zu haben, mussten wir das Markup duplizieren, auf die DOM-Elemente zugreifen und die CSS-Funktionen verwenden, um die Links im Bedienfeld anzuzeigen und auszublenden. Schauen wir uns eine alternative Navigationsleiste an, die von Vue erstellt wurde.

UeVue


Viele Webanwendungen haben dieselben Snippets, die auf verschiedenen Seiten verwendet werden. Zum Beispiel Navigationsleisten. Solche Einheiten sollten in Behältern aufbewahrt oder als zur Wiederverwendung geeignete Komponenten präsentiert werden. Vue stellt dem Entwickler eine Komponenten-Engine zur Verfügung, mit der Probleme wie das von uns in Betracht gezogene gelöst werden können. Vue-Komponenten sind in sich geschlossen und wiederverwendbar.

Beim Übertragen des Projekts zur Verwendung von Vue-Komponenten erstellen wir eine neue Datei, shared-vue.js . Vue, . .

 Vue.component("navigation", { props: ["isLoggedIn", "toggleLoggedIn"], template: `<div>             <header class="mdl-layout__header">       <div class="mdl-layout__header-row">         <!-- Title -->         <span class="mdl-layout-title">Shopping List</span>         <!-- Add spacer, to align navigation to the right -->         <div class="mdl-layout-spacer"></div>         <!-- Navigation. We hide it in small screens. -->         <nav class="mdl-navigation mdl-layout--large-screen-only">           <a class="mdl-navigation__link" href="index.html">Home</a>           <a class="mdl-navigation__link" href="history.html">History</a>           <a v-show="!isLoggedIn" @click="showLogin" style="cursor: pointer" class="mdl-navigation__link login">Login</a>           <a v-show="!isLoggedIn" @click="showRegister" style="cursor: pointer" class="mdl-navigation__link register">Register</a>           <a v-show="isLoggedIn" @click="logout" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>         </nav>       </div>     </header>     <div class="mdl-layout__drawer">       <span class="mdl-layout-title">Shopping List</span>       <nav class="mdl-navigation">         <a class="mdl-navigation__link" href="index.html">Home</a>         <a class="mdl-navigation__link" href="history.html">History</a>         <a v-show="!isLoggedIn" @click="showLogin" style="cursor: pointer" class="mdl-navigation__link login">Login</a>         <a v-show="!isLoggedIn" @click="showRegister" style="cursor: pointer" class="mdl-navigation__link register">Register</a>         <a v-show="isLoggedIn" @click="logout" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>       </nav>     </div>           </div>`, methods: {   showLogin: function() {     const loginDialog = document.querySelector("#login-dialog");     dialogPolyfill.registerDialog(loginDialog);     loginDialog.showModal();   },   showRegister: function() {     const registerDialog = document.querySelector("#register-dialog");     dialogPolyfill.registerDialog(registerDialog);     registerDialog.showModal();   },   logout: function() {     hoodie.account       .signOut()       .then(() => {         this.toggleLoggedIn();       })       .catch(error => {         alert("Could not logout");       });   } } }); 

Vue, navigation , , , Vue. — props . props — . , , , props . isLoggedIn , .

, template , , . , , JS, , Vue — v-show @click . v-show . Logout , isLoggedIn true , falseLogin Register . , Vue v-if v-else . . @clickv-on:click . showLogin , showRegister logout .

methods . logout , , this.toggleLoggedIn() , props . , props , , isLoggedin , . , Vue DOM.
index.html . , 59-84. .

 <navigation v-bind:is-logged-in="isLoggedIn" v-bind:toggle-logged-in="toggleLoggedIn"></navigation> 

JS- isLoggedIn toggleLoggedIn , , props , , kebab-case. v-bind . isLoggedIn . : v-bind , .

 <navigation :is-logged-in="isLoggedIn" :toggle-logged-in="toggleLoggedIn"></navigation> 

isLoggedIn , toggleLoggedIn — , Vue index-vue.js . .

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "",   items: [],   isLoggedIn: false }, computed: {   .....//   }, methods: {   toggleLoggedIn: function() {     this.isLoggedIn = !this.isLoggedIn;   },   ......//   } }); .....//   hoodie.account.get("session").then(function(session) { if (!session) {   //       vm.isLoggedIn = false; } else if (session.invalid) {   vm.isLoggedIn = false; } else {   //       vm.isLoggedIn = true; } }); 

Vue , , , , Vue. , Vue DOM , .


▍JavaScript


Login Register , . , , , . 171-244 index.html 100-158 history.html .

 <dialog id="login-dialog" class="mdl-dialog"> <h4 class="mdl-dialog__title">Login</h4> <div class="mdl-dialog__content">   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="text" id="login-username">       <label class="mdl-textfield__label" for="login-username">Username</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="password" id="login-password">       <label class="mdl-textfield__label" for="login-password">Password</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <span id="login-error"></span>     </div>   </div> </div> <div class="mdl-dialog__actions">   <button onclick="pageEvents.closeLogin()" type="button" class="mdl-button close">Cancel</button>   <button onclick="pageEvents.login()" type="button" class="mdl-button">Login</button> </div> </dialog> <dialog id="register-dialog" class="mdl-dialog"> <h4 class="mdl-dialog__title">Login</h4> <div class="mdl-dialog__content">   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="text" id="register-username">       <label class="mdl-textfield__label" for="register-username">Username</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="password" id="register-password">       <label class="mdl-textfield__label" for="register-password">Password</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <span id="register-error"></span>     </div>   </div> </div> <div class="mdl-dialog__actions">   <button onclick="pageEvents.closeRegister()" type="button" class="mdl-button close">Cancel</button>   <button onclick="pageEvents.register()" type="button" class="mdl-button">Register</button> </div> </dialog> 

, , shared.js index.js .

 //shared.js //   let loginDialog = document.querySelector("#login-dialog"); dialogPolyfill.registerDialog(loginDialog); let registerDialog = document.querySelector("#register-dialog"); dialogPolyfill.registerDialog(registerDialog); let closeLoginDialog = function() { loginDialog.close(); }; let closeRegisterDialog = function() { registerDialog.close(); }; let showAnonymous = function() { ... }; let showLoggedIn = function() { .... }; let signOut = function() { .... }; let updateDOMLoginStatus = () => { .... }; let login = function() { let username = document.querySelector("#login-username").value; let password = document.querySelector("#login-password").value; hoodie.account   .signIn({     username: username,     password: password   })   .then(function() {     showLoggedIn();     closeLoginDialog();     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "You logged in"     });   })   .catch(function(error) {     console.log(error);     document.querySelector("#login-error").innerHTML = error.message;   }); }; let register = function() { let username = document.querySelector("#register-username").value; let password = document.querySelector("#register-password").value; let options = { username: username, password: password }; hoodie.account   .signUp(options)   .then(function(account) {     return hoodie.account.signIn(options);   })   .then(account => {     showLoggedIn();     closeRegisterDialog();     return account;   })   .catch(function(error) {     console.log(error);     document.querySelector("#register-error").innerHTML = error.message;   }); }; export { register, login, closeRegisterDialog, closeLoginDialog, ... }; 

index.js.

 //index.js window.pageEvents = { closeLogin: shared.closeLoginDialog, showLogin: shared.showLoginDialog, closeRegister: shared.closeRegisterDialog, showRegister: shared.showRegisterDialog, login: shared.login, register: shared.register, signout: shared.signOut }; 

▍Vue


Vue . , .

 Vue.component("login-dialog", { data: function() {   return {     username: "",     password: ""   }; }, props: ["toggleLoggedIn"], template: `<dialog id="login-dialog" class="mdl-dialog">     <h4 class="mdl-dialog__title">Login</h4>     <div class="mdl-dialog__content">       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <input v-model="username" class="mdl-textfield__input" type="text" id="login-username">           <label class="mdl-textfield__label" for="login-username">Username</label>         </div>       </div>       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <input v-model="password" class="mdl-textfield__input" type="password" id="login-password">           <label class="mdl-textfield__label" for="login-password">Password</label>         </div>       </div>       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <span id="login-error"></span>         </div>       </div>     </div>     <div class="mdl-dialog__actions">       <button @click="closeLogin" type="button" class="mdl-button close">Cancel</button>       <button @click="login" type="button" class="mdl-button">Login</button>     </div>   </dialog>`, methods: {   closeLogin: function() {     const loginDialog = document.querySelector("#login-dialog");     dialogPolyfill.registerDialog(loginDialog);     loginDialog.close();   },   login: function(event) {     hoodie.account       .signIn({         username: this.username,         password: this.password       })       .then(() => {         this.toggleLoggedIn();         this.closeLogin();       })       .catch(error => {         console.log(error);         document.querySelector("#login-error").innerHTML = "Error loggin in";       });   } } }); 

data , props , template methods , Vue.component() .

, , Vue .

 //index.html <login-dialog v-bind:toggle-logged-in="toggleLoggedIn"></login-dialog> 

.

, , Vue. , , . , - Push API .

Zusammenfassung


-, JS, Vue.js. HTML, CSS JavaScript (jQuery), Vue . ES6 , .

Vue , , . , , , Vue. , , Vue .

, JS. — , Vue.

Liebe Leser! - ?

Source: https://habr.com/ru/post/de413311/


All Articles