Vue.js für Anfänger, Lektion 10: Formulare

In Lektion 10 des Vue-Kurses werden wir heute darüber sprechen, wie man mit Formularen arbeitet. Mit Formularen können Sie vom Benutzer eingegebene Daten erfassen. Darüber hinaus werden wir hier die Formularvalidierung diskutieren, dh überprüfen, was in sie eingegeben wird.







Vue.js Anfänger Lektion 1: Instanz Vue

Vue.js für Anfänger, Lektion 2: Bindungsattribute

Vue.js Anfänger Lektion 3: Bedingtes Rendern

Vue.js Anfänger Lektion 4: Listen rendern

Vue .js für Anfänger Lektion 5: Ereignisverarbeitung

Vue.js Anfänger Lektion 6: Binden von Klassen und Stilen

Vue.js Anfänger Lektion 7: berechnete Eigenschaften

Vue.js Anfänger Lektion 8: Komponenten

Vue. js für Anfänger Lektion 9: Benutzerdefinierte Ereignisse



Der Zweck der Lektion



Wir werden ein Formular erstellen, mit dem Website-Besucher Produktbewertungen einreichen können. Gleichzeitig ist es erforderlich, dass die Überprüfung nur gesendet werden kann, wenn alle Felder des Formulars ausgefüllt sind, die ausgefüllt werden müssen.



Anfangscode



Hier ist, was jetzt drin ist index.html:



<div id="app">
  <div class="cart">
    <p>Cart({{ cart.length }})</p>
  </div>

  <product :premium="premium" @add-to-cart="updateCart"></product>
</div>


Es sieht so aus main.js:



Vue.component('product', {
  props: {
    premium: {
      type: Boolean,
      required: true
    }
  },
  template: `
  <div class="product">
    <div class="product-image">
      <img :src="image" />
    </div>

    <div class="product-info">
      <h1>{{ title }}</h1>
      <p v-if="inStock">In stock</p>
      <p v-else>Out of Stock</p>
      <p>Shipping: {{ shipping }}</p>

      <ul>
        <li v-for="detail in details">{{ detail }}</li>
      </ul>
      <div
        class="color-box"
        v-for="(variant, index) in variants"
        :key="variant.variantId"
        :style="{ backgroundColor: variant.variantColor }"
        @mouseover="updateProduct(index)"
      ></div>

      <button
        v-on:click="addToCart"
        :disabled="!inStock"
        :class="{ disabledButton: !inStock }"
      >
        Add to cart
      </button>

    </div>
  </div>
  `,
  data() {
    return {
      product: 'Socks',
      brand: 'Vue Mastery',
      selectedVariant: 0,
      details: ['80% cotton', '20% polyester', 'Gender-neutral'],
      variants: [
        {
          variantId: 2234,
          variantColor: 'green',
          variantImage: './assets/vmSocks-green.jpg',
          variantQuantity: 10
        },
        {
          variantId: 2235,
          variantColor: 'blue',
          variantImage: './assets/vmSocks-blue.jpg',
          variantQuantity: 0
        }
      ]
    }
  },
    methods: {
      addToCart() {
        this.$emit('add-to-cart', this.variants[this.selectedVariant].variantId);
      },
      updateProduct(index) {
        this.selectedVariant = index;
        console.log(index);
      }
    },
    computed: {
      title() {
        return this.brand + ' ' + this.product;
      },
      image() {
        return this.variants[this.selectedVariant].variantImage;
      },
      inStock() {
        return this.variants[this.selectedVariant].variantQuantity;
      },
      shipping() {
        if (this.premium) {
          return "Free";
        } else {
          return 2.99
        }
      }
    }
})

var app = new Vue({
  el: '#app',
  data: {
    premium: true,
    cart: []
  },
  methods: {
    updateCart(id) {
      this.cart.push(id);
    }
  }
})


Aufgabe



Wir brauchen Website-Besucher, um Bewertungen zu Produkten abgeben zu können, aber unsere Website verfügt noch nicht über die Mittel, um Daten von Benutzern zu erhalten. Formen sind solche Mittel.



Die Lösung des Problems



Um die vor uns liegende Aufgabe zu lösen, müssen wir ein Formular erstellen. Beginnen wir mit der Erstellung einer neuen Komponente speziell für die Arbeit mit einem Formular. Nennen wir diese Komponente product-review. Dieser Name wurde gewählt, weil die Komponente den Betrieb des Formulars zur Erfassung von Produktbewertungen ermöglicht. Die Komponente product-reviewwird in der Komponente verschachtelt product.



Registrieren wir eine neue Komponente, beginnen mit der Erstellung ihrer Vorlage und statten sie mit einigen Daten aus:



Vue.component('product-review', {
  template: `
    <input>
  `,
  data() {
    return {
      name: null
    }
  }
})


Wie Sie sehen können, enthält die Komponentenvorlage ein Element und die Komponentendaten <input>eine Eigenschaft data, solange sie leer ist.



Wie binde ich das, was der Benutzer in ein Feld eingibt, an eine Eigenschaft name?



In den vorherigen Lektionen haben wir über die Datenbindung mithilfe von Anweisungen gesprochen v-bind, aber dann haben wir nur die Einwegbindung in Betracht gezogen. Der Datenfluss ging von der Eigenschaft, in der die Daten gespeichert sind, zu dem Steuerelement, das sie rendert. Und jetzt brauchen wir das, was der Benutzer in das Feld eingibt, in der Eigenschaft, namedie in den Komponentendaten gespeichert ist. Mit anderen Worten, wir möchten, dass der Datenfluss vom Eingabefeld zur Eigenschaft geleitet wird.



V-Modell-Richtlinie



Die Richtlinie v-modelermöglicht die Organisation der bidirektionalen Datenbindung. Wenn bei diesem Arbeitsschema etwas Neues im Eingabefeld angezeigt wird, führt dies zu einer Änderung der Daten. Wenn sich die Daten ändern, wird dementsprechend der Status des Steuerelements aktualisiert, das diese Daten verwendet.



Fügen wir dem Eingabefeld eine Direktive hinzu v-modelund binden dieses Feld an eine Eigenschaft nameaus den Komponentendaten.



<input v-model="name">


Fügen wir nun den vollständigen Formularcode zur Komponentenvorlage hinzu:



<form class="review-form" @submit.prevent="onSubmit">
  <p>
    <label for="name">Name:</label>
    <input id="name" v-model="name" placeholder="name">
  </p>

  <p>
    <label for="review">Review:</label>
    <textarea id="review" v-model="review"></textarea>
  </p>

  <p>
    <label for="rating">Rating:</label>
    <select id="rating" v-model.number="rating">
      <option>5</option>
      <option>4</option>
      <option>3</option>
      <option>2</option>
      <option>1</option>
    </select>
  </p>

  <p>
    <input type="submit" value="Submit">  
  </p>

</form>


Wie Sie sehen können, werden die v-modelFelder input, textareaund sind mit dem ausgestattet Richtlinie select. Bitte beachten Sie, dass beim Einrichten des Feldes selectein Modifikator verwendet wurde .number(wir werden weiter unten ausführlicher darauf eingehen). Auf diese Weise können Sie die entsprechenden Daten in einen Typ konvertieren Number, während diese normalerweise in einer Zeichenfolge dargestellt werden.



Ergänzen wir den Komponentendatensatz, indem wir die Daten hinzufügen, an die die oben beschriebenen Steuerelemente gebunden sind:



data() {
  return {
    name: null,
    review: null,
    rating: null
  }
}


Oben in der Formularvorlage sehen Sie, dass beim Senden des Formulars eine Methode aufgerufen wird onSubmit. Wir werden diese Methode bald erstellen. Aber lassen Sie uns zuerst über die Rolle des Bauens sprechen .prevent.



Dies ist ein Ereignismodifikator. Es verhindert, dass die Seite nach dem Eintreten eines Ereignisses neu geladen wird submit. Es gibt auch andere nützliche Ereignismodifikatoren . Es stimmt, wir werden nicht über sie sprechen.



Wir sind jetzt bereit, eine Methode zu erstellen onSubmit. Beginnen wir mit diesem Code:



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.name = null
  this.review = null
  this.rating = null
}


Wie Sie sehen können, erstellt diese Methode ein Objekt basierend auf den vom Benutzer eingegebenen Daten. Ein Verweis darauf wird in eine Variable geschrieben productReview. Hier sind wir in nullTropfeneigenschaftswerte name, review, rating. Aber die Arbeit ist noch nicht vorbei. Wir müssen noch irgendwohin schicken productReview. Wohin soll dieses Objekt gesendet werden?



Es ist sinnvoll, Produktbewertungen an derselben Stelle zu speichern, an der Komponentendaten gespeichert sind product. Da die Komponente product-reviewin einer Komponente verschachtelt ist product, können wir sagen, dass sie product-reviewein untergeordnetes Element der Komponente ist product. Wie wir in der vorherigen Lektion gelernt haben, können Sie Ereignisse verwenden, die mithilfe von generiert wurden, um Daten von untergeordneten Komponenten an übergeordnete Komponenten zu senden $emit.



Lassen Sie uns die Methode verfeinern onSubmit:



onSubmit() {
  let productReview = {
    name: this.name,
    review: this.review,
    rating: this.rating
  }
  this.$emit('review-submitted', productReview)
  this.name = null
  this.review = null
  this.rating = null
}


Jetzt generieren wir ein Ereignis mit einem Namen review-submittedund übergeben das neu erstellte Objekt darin productReview.



Als nächstes müssen wir das Abhören dieses Ereignisses organisieren, indem wir productFolgendes in die Vorlage einfügen :



<product-review @review-submitted="addReview"></product-review>


Diese Zeile lautet wie folgt: "Wenn ein Ereignis auftritt review-submitted, muss die addReviewKomponentenmethode ausgeführt werden product."



Hier ist der Code für diese Methode:



addReview(productReview) {
  this.reviews.push(productReview)
}


Diese Methode nimmt das Objekt productReview, das von der Methode stammt onSubmit, und fügt es dann in ein Array ein, reviewsdas in den Komponentendaten gespeichert ist product. Die Daten dieser Komponente enthalten jedoch noch kein solches Array. Fügen wir es also dort hinzu:



reviews: []


Wunderbar! Die Formularelemente sind jetzt an die Komponentendaten gebunden product-review. Diese Daten werden zum Erstellen des Objekts verwendet productReview. Und dieses Objekt wird beim Senden des Formulars an die Komponente übergeben product. Infolgedessen wird das Objekt productReviewdem Array hinzugefügt reviews, das in den Komponentendaten gespeichert ist product.



Produktbewertungen anzeigen



Jetzt müssen nur noch die Bewertungen der Website-Besucher auf der Produktseite angezeigt werden. Wir werden dies in der Komponente tun, productindem wir den entsprechenden Code über dem Code platzieren, mit dem die Komponente product-reviewin der Komponente platziert wird product.



<div>
 <h2>Reviews</h2>
 <p v-if="!reviews.length">There are no reviews yet.</p>
 <ul>
   <li v-for="review in reviews">
   <p>{{ review.name }}</p>
   <p>Rating: {{ review.rating }}</p>
   <p>{{ review.review }}</p>
   </li>
 </ul>
</div>


Hier erstellen wir mithilfe der Direktive eine Liste von Überprüfungen v-forund zeigen die im Objekt gespeicherten Daten in reviewPunktnotation an. 



Im Tag <p>überprüfen wir, ob sich etwas im Array befindet reviews(indem wir seine Länge überprüfen). Wenn das Array nichts enthält, drucken wir eine Nachricht There are no reviews yet.





Feedback-Formularseite



Formularvalidierung



Formulare enthalten häufig Felder, die vor dem Absenden des Formulars ausgefüllt werden müssen. Beispielsweise möchten wir nicht, dass Benutzer Bewertungen einreichen, in denen das Bewertungstextfeld leer ist.



Zum Glück unterstützt HTML5 das required. Seine Verwendung sieht folgendermaßen aus:



<input required >


Eine solche Konstruktion führt zu einer automatischen Anzeige einer Fehlermeldung, wenn der Benutzer versucht, ein Formular zu senden, in dem das erforderliche Feld leer ist.





Fehlermeldung Es



ist sehr schön, Standard-Formularfeldvalidatoren im Browser zu haben, da wir dadurch keine eigenen Feldvalidatoren erstellen können. Die Art und Weise, wie die Standarddatenprüfung durchgeführt wird, passt jedoch in bestimmten Fällen möglicherweise nicht zu uns. In dieser Situation ist es sinnvoll, einen eigenen Formularvalidierungscode zu schreiben.



Benutzerdefinierte Formularüberprüfung



Lassen Sie uns darüber sprechen, wie Sie Ihr eigenes Formularvalidierungssystem erstellen.



Fügen wir ein product-reviewArray zum Speichern von Fehlermeldungen in die Komponentendaten ein . Nennen wir es errors:



data() {
  return {
    name: null,
    review: null,
    rating: null,
    errors: []
  }
}


Wir möchten diesem Array Informationen zu Fehlern hinzufügen, die in Situationen auftreten, in denen Formularfelder leer sind. Wir sprechen über den folgenden Code:



if(!this.name) this.errors.push("Name required.")
if(!this.review) this.errors.push("Review required.")
if(!this.rating) this.errors.push("Rating required.")


Die erste dieser Zeilen weist das System namean, errorseine Fehlermeldung in das Array einzufügen, wenn das Feld leer ist Name required. Andere Zeichenfolgen, die die Felder reviewund validieren, funktionieren ähnlich rating. Wenn einer von ihnen leer ist, wird arrayeine Fehlermeldung an das Array gesendet.



Wo soll dieser Code abgelegt werden?



Da wir die Fehlermeldungen geschrieben werden auf das Array nur dann, wenn sie versuchen das Formular abzuschicken, es stellt sich heraus , dass die Felder sind name, reviewoder submitnicht gefüllt ist , können wir diesen Code in der Methode platzieren onSubmit. Außerdem werden wir den bereits darin enthaltenen Code neu schreiben und einige Überprüfungen hinzufügen:



onSubmit() {
  if(this.name && this.review && this.rating) {
    let productReview = {
      name: this.name,
      review: this.review,
      rating: this.rating
    }
    this.$emit('review-submitted', productReview)
    this.name = null
    this.review = null
    this.rating = null
  } else {
    if(!this.name) this.errors.push("Name required.")
    if(!this.review) this.errors.push("Review required.")
    if(!this.rating) this.errors.push("Rating required.")
  }
}


Nun überprüfen wir die Felder name, reviewund rating. Wenn in all diesen Feldern Daten vorhanden sind, erstellen wir ein darauf basierendes Objekt productReviewund senden es an die übergeordnete Komponente. Dann werden die entsprechenden Eigenschaften zurückgesetzt.



Wenn mindestens eines der Felder leer ist, wird errorseine Fehlermeldung in das Array eingefügt , je nachdem, was der Benutzer vor dem Absenden des Formulars nicht eingegeben hat.



Sie müssen nur noch diese Fehler anzeigen, was mit dem folgenden Code möglich ist:



<p v-if="errors.length">
  <b>Please correct the following error(s):</b>
  <ul>
    <li v-for="error in errors">{{ error }}</li>
  </ul>
</p>


Hier wird eine Direktive verwendet, v-ifmit der wir das Array errorsauf das Vorhandensein von Fehlermeldungen überprüfen (tatsächlich analysieren wir die Länge des Arrays). Wenn sich etwas im Array befindet, wird ein Element angezeigt <p>, das bei Anwendung v-foreine Liste der Fehler des Arrays anzeigt errors.





Fehlermeldungen



Wir haben jetzt ein eigenes Formularvalidierungssystem.



Verwenden des Modifikators .number



Der .numberin der Direktive v-modelverwendete Modifikator kann sehr nützlich sein. Beachten Sie jedoch bei der Anwendung, dass ein Problem damit verbunden ist. Wenn der entsprechende Wert leer ist, wird er als Zeichenfolge und nicht als Zahl dargestellt. Das Vue-Rezeptbuch bietet eine Lösung für dieses Problem. Es besteht darin, den entsprechenden Wert explizit in einen numerischen Typ umzuwandeln:



Number(this.myNumber)


Werkstatt



Fügen Sie dem Formular die folgende Frage hinzu: "Würden Sie dieses Produkt empfehlen?" Stellen Sie sicher, dass der Benutzer mit den Optionsfeldern Ja und Nein darauf antworten kann. Überprüfen Sie die Antwort auf diese Frage und fügen Sie die relevanten Daten in das Objekt ein productReview.





Ergebnis



Heute haben wir über das Arbeiten mit Formularen gesprochen. Hier ist das Wichtigste, was Sie heute gelernt haben:



  • Mit der Direktive können Sie die bidirektionale Datenbindung zu Formularelementen organisieren v-model.
  • Der Modifikator .numberweist Vue an, den entsprechenden Wert in einen numerischen Typ umzuwandeln. Bei der Arbeit damit gibt es jedoch ein Problem, das damit zusammenhängt, dass leere Werte Zeichenfolgen bleiben.
  • Mit dem Ereignismodifikator .preventkönnen Sie das erneute Laden von Seiten nach dem Absenden des Formulars verhindern.
  • Mit Vue können Sie einen relativ einfachen Mechanismus für die Validierung benutzerdefinierter Formulare implementieren.


Hast du heute deine Hausaufgaben gemacht?



Vue.js Anfänger Lektion 1: Instanz Vue

Vue.js für Anfänger, Lektion 2: Bindungsattribute

Vue.js Anfänger Lektion 3: Bedingtes Rendern

Vue.js Anfänger Lektion 4: Listen rendern

Vue .js für Anfänger Lektion 5: Ereignisverarbeitung

Vue.js Anfänger Lektion 6: Binden von Klassen und Stilen

Vue.js Anfänger Lektion 7: berechnete Eigenschaften

Vue.js Anfänger Lektion 8: Komponenten

Vue. js für Anfänger Lektion 9: Benutzerdefinierte Ereignisse






All Articles