初心者向けのVue.js、レッスン10:フォーム

今日は、Vueコースのレッスン10で、フォームの操作方法について説明します。フォームを使用すると、ユーザーが入力したデータを収集できます。さらに、ここでは、フォームの検証、つまり、フォームに何が入力されているかを確認する方法について説明します。







Vue.js初心者レッスン1:インスタンスVue

初心者向けVue.js、レッスン2:バインディング属性

Vue.js初心者レッスン3:条件付きレンダリング

Vue.js初心者レッスン4:リストレンダリング

Vue .js初心者向けレッスン5:イベント処理

Vue.js初心者向けレッスン6:クラスとスタイルのバインド

Vue.js初心者向けレッスン7:計算されたプロパティ

Vue.js初心者向けレッスン8:コンポーネント

Vue。初心者向けjsレッスン9:カスタムイベント



レッスンの目的



サイト訪問者が製品レビューを送信できるフォームを作成します。この場合、フォームのすべてのフィールドに入力した場合にのみレビューを送信できる必要があり、入力する必要があります。



初期コード



これが今の内容index.htmlです:



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

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


それはこのように見えます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);
    }
  }
})


仕事



サイト訪問者が製品のレビューを残せるようにしたいのですが、私たちのサイトにはまだユーザーからデータを受け取る手段がありません。フォームはそのような手段です。



問題の解決策



私たちにとって、私たちの前のタスクを解決するには、フォームを作成する必要があります。フォームを操作するための新しいコンポーネントを作成することから始めましょう。このコンポーネントを呼び出しましょうproduct-review。この名前が選ばれたのは、コンポーネントが製品レビューの収集を目的としたフォームの操作を提供するためです。コンポーネントproduct-reviewは、コンポーネント内にネストされますproduct



新しいコンポーネントを登録し、そのテンプレートの作成を開始して、いくつかのデータを装備しましょう。



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


ご覧のとおり、コンポーネントテンプレートには要素<input>があり、コンポーネントデータdataには空のプロパティがあります



ユーザーがフィールドに入力した内容をプロパティにバインドするにはどうすればよいnameですか?



前のレッスンでは、ディレクティブを使用したデータバインディングについて説明しましたv-bindが、その後は一方向のバインディングのみを検討しました。データフローは、データを格納するプロパティから、データをレンダリングするコントロールに送られました。そして今、ユーザーがフィールドに入力するものはname、コンポーネントデータに格納されているプロパティにある必要があります。つまり、データフローを入力フィールドからプロパティに転送する必要があります。



Vモデルディレクティブ



このディレクティブv-modelにより、双方向のデータバインディングを整理できます。この作業スキームでは、入力フィールドに何か新しいものが表示された場合、これはデータの変更につながります。また、それに応じて、データが変更されると、このデータを使用するコントロールの状態が更新されます。



入力フィールドにディレクティブを追加し、v-modelこのフィールドをnameコンポーネントデータのプロパティにバインドしてみましょう



<input v-model="name">


次に、完全なフォームコードをコンポーネントテンプレートに追加しましょう。



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


ご覧のとおり、v-modelフィールドinputtextareaおよびにディレクティブが装備されていselectます。フィールドを設定するときselectに、修飾子が使用されたことに注意してください.number(これについては以下で詳しく説明します)。これにより、対応するデータをタイプNumber変換できますが、通常は文字列形式で表示されます。



上記のコントロールがバインドされているデータをコンポーネントデータセットに追加して、コンポーネントデータセットを補足しましょう。



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


フォームテンプレートの上部に、フォームが送信されると、メソッドが呼び出されることがわかりますonSubmit。このメソッドはまもなく作成されます。しかし、最初に、建設の役割について話しましょう.prevent



これはイベント修飾子です。イベントが発生した後にページが再ロードされるのを防ぎますsubmit。他にも便利なイベント修飾子があります。確かに、私たちはそれらについて話しません。



これで、メソッドを作成する準備ができましたonSubmit。このコードから始めましょう:



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


ご覧のとおり、このメソッドは、ユーザーが入力したデータに基づいてオブジェクトを作成します。それへの参照は変数に書き込まれますproductReview。ここでは、中にドロップnullプロパティ値namereviewrating。しかし、作業はまだ終わっていません。まだどこかに送る必要がありますproductReview。このオブジェクトをどこに送信しますか?



コンポーネントデータが保存されているのと同じ場所に製品レビューを保存することは理にかなっていますproduct。コンポーネントがコンポーネントproduct-review内にネストされproductているproduct-reviewとすると、それはコンポーネントの子であると言えますproduct。前のレッスンで学習したように、を使用して生成されたイベントを使用して、子コンポーネントから親コンポーネントにデータを送信できます$emit



メソッドを改良しましょう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
}


ここで、名前を使用してイベントを生成しreview-submitted、新しく作成されたオブジェクトをその中に渡しますproductReview



次に、テンプレートにproduct以下を配置して、このイベントのリスニングを整理する必要があります。



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


この行は次のようreview-submittedになります。「イベントが発生した場合、addReviewコンポーネントメソッドを実行する必要がありますproduct。」



このメソッドのコードは次のとおりです。



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


このメソッドは、メソッドproductReviewから取得したオブジェクト取得し、それをコンポーネントデータに格納されてonSubmitいる配列に配置しreviewsますproductしかし、このコンポーネントのデータにはまだそのような配列はありません。そこに追加しましょう:



reviews: []


素晴らしい!これで、フォーム要素がコンポーネントデータにバインドされましたproduct-reviewこのデータは、オブジェクトの作成に使用されますproductReviewそして、このオブジェクトは、フォームが送信されると、コンポーネントに渡されますproductその結果、オブジェクトがproductReview配列reviews追加され、コンポーネントデータに格納されますproduct



製品レビューの表示



残っているのは、サイト訪問者が残したレビューを製品ページに表示することだけです。コンポーネントがコンポーネントproductに配置されるコードの上に対応するコードを配置することにより、コンポーネントでこれproduct-reviewを行います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>


ここでは、ディレクティブv-for使用してレビューのリストを作成し、reviewドット表記を使用してオブジェクトに格納されているデータを表示します。 



タグで<p>は、配列に何かがあるかどうかをチェックしますreviews(長さをチェックします)。配列に何もない場合は、メッセージを出力しますThere are no reviews yet





フィードバックフォームページ



フォームの検証



多くの場合、フォームには、フォームを送信する前に入力する必要のあるフィールドが含まれています。たとえば、レビューテキストフィールドが空のレビューをユーザーが送信することは望ましくありません。



幸いなことに、HTML5はをサポートしていrequiredます。その使用法は次のようになります。



<input required >


このような構成では、ユーザーが必須フィールドが空のフォームを送信しようとすると、エラーメッセージが自動的に表示されます。





エラーメッセージ



ブラウザに標準のフォームフィールド検証ツールがあると、独自のフィールド検証ツールを作成する必要がなくなるため、非常に便利です。ただし、標準のデータチェックの実行方法は、特別な場合には、私たちに適さない場合があります。この状況では、独自のフォーム検証コードを作成するのが理にかなっています。



カスタムフォームの検証



独自のフォーム検証システムを作成する方法について説明しましょう。エラーメッセージ



をコンポーネントデータにproduct-review格納するため配列を含めましょうそれを呼びましょうerrors



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


フォームフィールドが空の状況で発生するエラーに関する情報をこの配列に追加したいと思います。次のコードについて話しています。



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


これらの行の最初の行は、フィールドnameが空の場合にerrorsエラーメッセージを配列に配置するようにシステム指示しますName requiredreviewおよびフィールドを検証する他の文字列も同様に機能しratingます。それらのいずれかが空の場合array、エラーメッセージが配列に送信さます。



このコードをどこに置くか?



フォームを送信しようとすると、それはフィールドがあることが判明した場合にのみ、我々は、エラーメッセージが配列に書き込まれるようにしたいのでnamereviewまたはされてsubmit充填されていない、私たちは、この方法では、このコードを配置することができますonSubmit。さらに、すでに含まれているコードを書き直し、いくつかのチェックを追加します。



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.")
  }
}


今、私たちはフィールドをチェックしnamereviewそしてratingこれらすべてのフィールドにデータがある場合は、それらに基づいてオブジェクトを作成し、productReviewそれを親コンポーネントに送信します。次に、対応するプロパティがリセットされます。



フィールドの少なくとも1つが空の場合errors、フォームを送信する前にユーザーが入力しなかった内容に応じて、配列にエラーメッセージ入力します。



残っているのは、これらのエラーを表示することだけです。これは、次のコードで実行できます。



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


ここでは、ディレクティブを使用v-ifして、配列errorsにエラーメッセージが存在するかどうかを確認します(実際には、配列の長さを分析します)。配列に何かがある場合、要素が表示されます<p>。これを適用v-forすると、配列からのエラーのリストが表示されますerrors





エラーメッセージ



これで、独自のフォーム検証システムができました。



.nu​​mber修飾子の使用



.numberディレクティブで使用される 修飾子はv-model非常に便利です。ただし、それを適用するときは、それに関連する1つの問題があることに注意してください。対応する値が空の場合、数値ではなく文字列として表されます。Vueのレシピブックは、この問題に対する解決策を提供しています。これは、対応する値を数値タイプに明示的に変換することで構成されます。



Number(this.myNumber)


ワークショップ



フォームに次の質問を追加します:「この製品をお勧めしますか?」ユーザーが「はい」と「いいえ」のラジオボタンを使用して答えられるようにします。この質問への回答を確認し、関連するデータをオブジェクトに含めますproductReview



  • これは、この問題を解決するために使用できるテンプレートです。
  • これが問題解決策です。


結果



今日は、フォームの操作について話しました。今日学んだ最も重要なことは次のとおりです。



  • ディレクティブを使用して、フォーム要素への双方向データバインディングを整理できますv-model
  • 修飾子.numberは、対応する値を数値タイプにキャストするようにVueに指示します。しかし、それを使用する場合、空の値が文字列のままであるという事実に関連する1つの問題があります。
  • イベント修飾子を.prevent使用すると、フォームの送信後にページが再読み込みされないようにすることができます。
  • Vueを使用すると、カスタムフォーム検証用の非常に単純なメカニズムを実装できます。


今日は宿題をしましたか?



Vue.js初心者レッスン1:インスタンスVue

初心者向けVue.js、レッスン2:バインディング属性

Vue.js初心者レッスン3:条件付きレンダリング

Vue.js初心者レッスン4:リストレンダリング

Vue .js初心者向けレッスン5:イベント処理

Vue.js初心者向けレッスン6:クラスとスタイルのバインド

Vue.js初心者向けレッスン7:計算されたプロパティ

Vue.js初心者向けレッスン8:コンポーネント

Vue。初心者向けjsレッスン9:カスタムイベント






All Articles