→ 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フィールドinput、textareaおよびにはディレクティブが装備されてい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プロパティ値name、review、rating。しかし、作業はまだ終わっていません。まだどこかに送る必要があります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 required。reviewおよびフィールドを検証する他の文字列も同様に機能しratingます。それらのいずれかが空の場合array、エラーメッセージが配列に送信されます。
このコードをどこに置くか?
フォームを送信しようとすると、それはフィールドがあることが判明した場合にのみ、我々は、エラーメッセージが配列に書き込まれるようにしたいので
name、reviewまたはされて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.")
}
}
今、私たちはフィールドをチェックし
name、reviewそして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。

エラーメッセージ
これで、独自のフォーム検証システムができました。
.number修飾子の使用
.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:カスタムイベント
