Vue.js للمبتدئين الدرس 7: الخصائص المحسوبة
→ Vue.js للمبتدئين الدرس 8: المكونات
الغرض من الدرس
الهدف الرئيسي من هذا الدرس هو إنشاء مكوننا الأول واستكشاف آليات تمرير البيانات إلى المكونات.
الكود الأولي
إليك الكود الخاص بالملف
index.html
في العلامة <body>
التي سنبدأ بها:
<div id="app">
<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 class="cart">
<p>Cart({{ cart }})</p>
</div>
</div>
</div>
</div>
ها هو الكود
main.js
:
var app = new Vue({
el: '#app',
data: {
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
}
],
cart: 0,
},
methods: {
addToCart() {
this.cart += 1;
},
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;
}
}
})
مهمة
لا نحتاج إلى تحديد موقع جميع البيانات والأساليب والخصائص المحسوبة في تطبيق Vue في مثيل الجذر Vue. بمرور الوقت ، سيؤدي ذلك إلى رمز سيكون من الصعب جدًا الحفاظ عليه. بدلاً من ذلك ، نود تقسيم الكود إلى أجزاء معيارية يسهل العمل معها وتجعل التطوير أكثر مرونة.
حل المشكلة
لنبدأ بأخذ الكود الموجود ونقله إلى مكون جديد.
هكذا
main.js
يتم تسجيل المكون في الملف :
Vue.component('product', {})
الوسيطة الأولى هي اسم المكون الذي اخترناه. والثاني هو كائن خيارات مشابه للكائن الذي استخدمناه لإنشاء مثيل Vue في البرامج التعليمية السابقة.
في مثال Vue ، استخدمنا خاصية
el
لتنظيم ارتباطها بعنصر DOM. في حالة المكون ، يتم استخدام خاصية template
تحدد كود HTML الخاص بالمكون.
دعنا نصف قالب المكون في كائن بالخيارات:
Vue.component('product', {
template: `
<div class="product">
… // HTML-, product
</div>
`
})
هناك عدة طرق لإنشاء قوالب في Vue. نحن الآن نستخدم نموذجًا حرفيًا ، يتم تضمين محتوياته بين علامتي اقتباس في الخلف.
إذا اتضح أنه لن يتم وضع رمز القالب في عنصر جذر واحد ، مثل عنصر
<div>
به فئة product
، فسيؤدي ذلك إلى ظهور رسالة الخطأ التالية:
Component template should contain exactly one root element
بمعنى آخر ، يمكن لقالب المكون إرجاع عنصر واحد فقط.
على سبيل المثال ، القالب التالي منسق بشكل جيد لأنه ممثل بعنصر واحد فقط:
Vue.component('product', {
template: `<h1>I'm a single element!</h1>`
})
ولكن إذا كان القالب يحتوي على عدة أشقاء ، فلن يعمل. هذا مثال على نمط سيء:
Vue.component('product', {
template: `
<h1>I'm a single element!</h1>
<h2>Not anymore</h2>
`
})
نتيجة لذلك ، اتضح أنه إذا كان يجب أن يتضمن القالب العديد من العناصر ، على سبيل المثال ، مجموعة من العناصر المضمنة في
<div>
صنفنا product
، فيجب وضع هذه العناصر في عنصر حاوية خارجي. نتيجة لذلك ، سيحتوي القالب على عنصر جذر واحد فقط.
الآن بعد أن احتوى القالب على كود HTML الذي كان موجودًا في الملف
index.html
، يمكننا إضافة بيانات وطرق وخصائص محسوبة إلى المكون الذي كان سابقًا في مثيل root Vue:
Vue.component('product', {
template: `
<div class="product">
…
</div>
`,
data() {
return {
//
}
},
methods: {
//
},
computed: {
//
}
})
كما ترى ، فإن بنية هذا المكون هي تقريبًا نفس بنية مثيل Vue الذي عملنا معه سابقًا. هل لاحظت أن
data
هذه ليست خاصية الآن ، ولكنها طريقة لكائن مع خيارات؟ لماذا هو كذلك؟
النقطة المهمة هي أن المكونات يتم إنشاؤها غالبًا بخطط لإعادة استخدامها. إذا كان لدينا العديد من المكونات
product
، فنحن بحاجة إلى التأكد من أن لكل منها مثيلاتها الخاصة data
. نظرًا لأنها data
الآن دالة تقوم بإرجاع كائن مع البيانات ، فإن كل مكون مضمون لتلقي مجموعة البيانات الخاصة به. إذا لم data
يكن الكيان دالة ، فإن كل مكونproduct
أينما تم استخدام هذه المكونات ، سوف تحتوي على نفس البيانات. وهذا يتعارض مع فكرة المكونات القابلة لإعادة الاستخدام.
الآن بعد أن قمنا بنقل الكود المتعلق بالمنتج إلى مكون أصلي
product
، تبدو الكود الخاص بوصف مثيل الجذر Vue كما يلي:
var app = new Vue({
el: '#app'
})
الآن نحتاج فقط إلى وضع المكون
product
في كود الملف index.html
. سيبدو مثل هذا:
<div id="app">
<product></product>
</div>
إذا قمت بإعادة تحميل صفحة التطبيق الآن ، فسوف تعود إلى شكلها السابق.
صفحة التطبيق
إذا نظرت الآن في أدوات مطور Vue ، فستلاحظ وجود كيان جذر ومكون منتج.
تحليل تطبيق باستخدام Vue Developer Tools
الآن ، فقط لتوضيح إمكانية إعادة استخدام المكونات ، دعنا نضيف
index.html
بعض المكوناتالإضافية إلى الكودproduct
. في الواقع ، هذه هي الطريقة التي يتم بها تنظيم إعادة استخدام المكونات. index.html
سيبدوالرمزكما يلي:
<div id="app">
<product></product>
<product></product>
<product></product>
</div>
وستعرض الصفحة ثلاث نسخ من بطاقة المنتج.
يتم عرض العديد من بطاقات المنتجات في صفحة واحدة ،
يرجى ملاحظة أننا سنعمل في المستقبل مع مكون واحد
product
، لذلكindex.html
سيبدوالرمزكما يلي:
<div id="app">
<product></product>
</div>
مهمة
غالبًا ما تحتاج التطبيقات إلى مكونات لقبول البيانات ومعلمات الإدخال من الكيانات الرئيسية. في هذه الحالة ، يكون أصل المكون
product
هو مثيل الجذر Vue نفسه.
دع مثيل root Vue يحتوي على وصف لبعض البيانات. تشير هذه البيانات إلى ما إذا كان المستخدم صاحب حساب ممتاز. قد يبدو رمز وصف مثيل Vue بالشكل التالي:
var app = new Vue({
el: '#app',
data: {
premium: true
}
})
دعنا نقرر أنه يحق للمستخدمين المميزين الحصول على شحن مجاني.
هذا يعني أننا نريد أن يقوم المكون
product
بإخراج premium
معلومات تكلفة شحن مختلفة اعتمادًا على ما هو مكتوب في خاصية مثيل الجذر Vue.
كيف يمكنني إرسال البيانات المخزنة في خاصية
premium
مثيل root Vue إلى الطفل وهو المكون product
؟
حل المشكلة
في Vue ، لنقل البيانات من الكيانات الأصلية إلى
props
العناصر الفرعية ، يتم استخدام خاصية كائن مع الخيارات الموضحة بواسطة المكونات. هذا كائن يصف معلمات الإدخال للمكون ، والتي يجب تعيين قيمها بناءً على البيانات الواردة من الكيان الرئيسي.
لنبدأ بوصف نوع معلمات الإدخال التي يتوقع المكون تلقيها
product
. للقيام بذلك ، أضف الخاصية المقابلة إلى الكائن بالخيارات المستخدمة عند إنشائه:
Vue.component('product', {
props: {
premium: {
type: Boolean,
required: true
}
},
// , ,
})
لاحظ أن هذا يستخدم القدرة المدمجة في Vue للتحقق من صحة المعلمات التي تم تمريرها إلى المكون. على وجه التحديد ، نشير إلى نوع معلمة الإدخال وما
premium
هي Boolean
هذه المعلمة المطلوبة من خلال الضبط required
على true
.
بعد ذلك ، دعنا نجري تغييرًا على القالب الذي يعرض المعلمات التي تم تمريرها إلى الكائن. من خلال عرض قيمة الخاصية
premium
على الصفحة ، سنتأكد من أن الآلية التي نتحرى عنها تعمل بشكل صحيح.
<p>User is premium: {{ premium }}</p>
حتى الآن ، كل شيء يسير على ما يرام.
product
يعرف المكون أنه سيتلقى معلمة النوع المطلوبة لتشغيله Boolean
. لقد قمنا بإعداد مكان لعرض البيانات ذات الصلة.
لكننا لم نمرر المعلمة إلى
premium
المكون حتى الآن . يمكنك القيام بذلك باستخدام سمة مخصصة تشبه "السطر" الذي يؤدي إلى مكون يمكن من خلاله نقل معلمات الإدخال ، وعلى وجه الخصوص premium
.
دعنا نعدل الكود في
index.html
:
<div id="app">
<product :premium="premium"></product>
</div>
لنقم بتحديث الصفحة.
إخراج البيانات التي تم تمريرها إلى المكون
يتم الآن تمرير معلمات الإدخال إلى المكون. دعنا نتحدث بالضبط عما فعلناه للتو.
نقوم بتمرير المكون إلى معلمة إدخال ، أو تسمى "سمة مخصصة"
premium
. نربط هذه السمة المخصصة باستخدام بنية القولون بخاصيةpremium
مخزنة في بيانات مثيل Vue الخاصة بنا.
الآن يمكن أن ينتقل مثيل root Vue إلى
premium
المكون الفرعيproduct
. نظرًا لأن السمة مرتبطة بخاصيةpremium
من بيانات مثيل Vue ،premium
سيتم دائمًا تمريرالقيمة الحاليةإلى المكونproduct
.
يوضح الشكل أعلاه ، أي النقش
User is premium: true
، أن كل شيء تم بشكل صحيح.
لقد تحققنا الآن من أن آلية نقل البيانات التي ندرسها تعمل كما هو متوقع. إذا نظرت إلى أدوات مطور Vue ، فقد تبين أن المكون
Product
يحتوي الآن على معلمة إدخال premium
تخزن قيمة true
.
معلمة الإدخال للمكون
الآن بعد أن دخلت البيانات حول ما إذا كان المستخدم لديه حساب مميز في المكون ، فلنستخدم هذه البيانات لعرض معلومات تكلفة الشحن على الصفحة. دعونا لا ننسى أنه إذا تم
premium
تعيينالمعلمةعلى قيمةtrue
، فيحق للمستخدم الشحن المجاني. دعونا ننشئ خاصية محسوبة جديدةshipping
ونستخدم المعلمة فيهاpremium
:
shipping() {
if (this.premium) {
return "Free";
} else {
return 2.99
}
}
إذا
this.premium
المخزنة في معلمة true
، الخاصية المحسوبة shipping
سيعود Free
. وإلا فإنه سيعود 2.99
.
دعنا نزيل كود إخراج قيمة المعلمة من قالب المكون
premium
. الآن العنصر <p>Shipping: {{ shipping }}</p>
الذي كان موجودًا في الكود الذي بدأنا به اليوم سيكون قادرًا على عرض معلومات حول تكلفة الشحن.
يحصل المستخدمون المتميزون على
نص تسليم مجاني
Shipping: Free
يظهر على الصفحة نظرًا لحقيقة أن المكون يتم إرسال معلمة إدخالpremium
مضبوطة على قيمةtrue
.
رائع! لقد تعلمنا الآن كيفية نقل البيانات من الكيانات الأم إلى الأطفال وتمكنا من استخدام هذه البيانات في المكون لإدارة تكلفة شحن البضائع.
بالمناسبة ، تجدر الإشارة إلى أنه لا يجب تغيير معلمات الإدخال الخاصة بهم في المكونات الفرعية.
ورشة عمل
أنشئ مكونًا جديدًا
product-details
يجب أن يستخدم معلمة إدخال details
ويكون مسؤولاً عن عرض جزء بطاقة المنتج الذي تم تكوينه مسبقًا باستخدام الكود التالي:
<ul>
<li v-for="detail in details">{{ detail }}</li>
</ul>
إليك نموذج يمكنك استخدامه لحل هذه المشكلة.
هذا هو الحل للمشكلة.
النتيجة
كان اليوم أول مقدمة لك عن مكونات Vue. هذا ما تعلمته:
- المكونات عبارة عن كتل من التعليمات البرمجية يتم تقديمها كعناصر مخصصة.
- تجعل المكونات تطبيقك أسهل في الإدارة عن طريق تقسيمه إلى أجزاء قابلة لإعادة الاستخدام. تحتوي على أوصاف للمكون المرئي ووظائف الجزء المقابل من التطبيق.
- يتم تمثيل بيانات المكون بواسطة طريقة
data()
كائن مع خيارات. - تُستخدم معلمات الإدخال (
props
) لتمرير البيانات من الكيانات الرئيسية إلى الكيانات الفرعية . - يمكننا وصف متطلبات معلمات الإدخال التي يأخذها المكون.
- .
- .
- Vue .
هل تستخدم أدوات مطور Vue؟
→ درس المبتدئين Vue.js 1: المثال Vue
→ Vue.js للمبتدئين ، الدرس 2: سمات الربط
← Vue.js الدرس 3: العرض الشرطي
→ Vue.js للمبتدئين الدرس 4: عرض القوائم
→ Vue .js للمبتدئين الدرس الخامس: معالجة الأحداث
← Vue.js للمبتدئين الدرس 6: فئات وأنماط الربط
← Vue.js للمبتدئين الدرس 7: الخصائص المحسوبة
← مبتدئين Vue.js الدرس 8: المكونات