→ درس المبتدئين 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
ونرسلها إلى المكون الرئيسي. ثم يتم إعادة تعيين الخصائص المقابلة.
إذا كان أحد الحقول على الأقل فارغًا ، نضع
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
المستخدم في التوجيه v-model
مفيدًا جدًا. ولكن عند تطبيقه ، ضع في اعتبارك أن هناك مشكلة واحدة مرتبطة به. إذا كانت القيمة المقابلة فارغة ، فسيتم تمثيلها كسلسلة وليس كرقم. و صفة فيو الكتاب يقدم حلا لهذه المشكلة. يتمثل في تحويل القيمة المقابلة صراحةً إلى نوع رقمي:
Number(this.myNumber)
ورشة عمل
أضف السؤال التالي إلى النموذج: "هل تنصح بهذا المنتج؟" اجعلها حتى يتمكن المستخدم من الإجابة عليها باستخدام أزرار الاختيار "نعم" و "لا". تحقق من إجابة هذا السؤال وقم بتضمين البيانات ذات الصلة في الكائن
productReview
.
النتيجة
تحدثنا اليوم عن العمل مع النماذج. إليك أهم شيء تعلمته اليوم:
- يمكنك استخدام التوجيه لتنظيم ربط البيانات ثنائي الاتجاه لعناصر النموذج
v-model
. .number
يخبر المُعدِّل Vue أن يلقي القيمة المقابلة إلى نوع رقمي. ولكن عند العمل بها ، هناك مشكلة واحدة تتعلق بحقيقة أن القيم الفارغة تظل سلاسل..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: أحداث مخصصة