حان الوقت الآن للتعمق أكثر في إطار العمل Vue وإنشاء مكوّن مخصَّص، إذ سنبدأ بإنشاء مكوِّن لتمثيل كل عنصر في قائمة المهام، كما سنتعرّف على بعض المفاهيم المهمة مثل استدعاء المكونات ضمن مكونات أخرى وتمرير البيانات إليها باستخدام الخاصيات Props وحفظ حالة البيانات.
ملاحظة: إذا كنت بحاجة إلى التحقق من شيفرتك مقابل نسخة شيفرتنا، فيمكنك العثور على نسخة نهائية من نموذج شيفرة تطبيق Vue في المستودع todo-vue أو يمكنك الحصول على إصدار حي وقيد التشغيل منه.
- المتطلبات الأساسية: الإلمام بأساسيات لغات HTML وCSS وجافاسكربت JavaScript، ومعرفة استخدام سطر الأوامر أو الطرفية، إذ تُكتَب مكونات Vue بوصفها مجموعة من كائنات جافاسكربت التي تدير بيانات التطبيق وصيغة القوالب المستنِدة إلى لغة HTML المرتبطة مع بنية DOM الأساسية، وستحتاج إلى طرفية مثبَّت عليها node و npm لتثبيت Vue ولاستخدام بعض ميزاته الأكثر تقدمًا مثل مكونات الملف المفرد Single File Components أو دوال التصيير Render.
- الهدف: تعلّم كيفية إنشاء مكوِّن Vue وتصييره ضمن مكوِّن آخر، وتمرير البيانات إليه باستخدام الخاصيات، وحفظ حالته.
إنشاء المكون ToDoItem
لننشئ مكوننا الأول الذي سيعرض عنصر مهمة واحدًا، إذ سنستخدمه لبناء قائمة المهام.
- أنشئ ملفًا جديدًا بالاسم ToDoItem.vue في المجلد moz-todo-vue/src/components، ثم افتح الملف في محرّر الشيفرات.
-
أنشئ قسم قالب المكوِّن من خلال إضافة العنصر
<template></template>
في أعلى الملف. -
أنشئ القسم
<script></script>
بعد قسم القالب، ثم أضف فيه كائن تصدير افتراضيexport default {}
، وهو كائن مكوِّنك.
يجب أن يبدو ملفك الآن كما يلي:
<template> </template> <script> export default {}; </script>
يمكننا الآن إضافة محتوى فعلي إلى الملف ToDoItem، إذ يُسمَح حاليًا لقوالب Vue بإضافة عنصر جذر واحد فقط، كما يجب استخدام عنصر واحد لتغليف كل شيء ضمن قسم القالب، ولكن سيتغير ذلك في الإصدار رقم 3 من Vue،إذ سنستخدِم العنصر <div>
لهذا العنصر الجذر.
-
أضف عنصر
<div>
فارغ ضمن قالب المكوِّن. -
أضِف مربع اختيار وعنوانًا
label
مقابلًا ضمن العنصر<div>
. أضِف السمةid
إلى مربع الاختيار، والسمةfor
التي تربط مربع الاختيار مع العنوانlabel
كما هو موضّح فيما يلي:
<template> <div> <input type="checkbox" id="todo-item" /> <label for="todo-item">My Todo Item</label> </div> </template>
استخدام المكون TodoItem ضمن تطبيقك
لم نضِف المكوِّن إلى تطبيقنا حتى الآن، لذلك لا توجد طريقة لاختباره ومعرفة ما إذا كان كل شيء على ما يرام أم لا، إذًا لنضفه الآن.
- افتح الملف App.vue مرة أخرى.
-
أضِف السطر التالي لاستيراد المكون
ToDoItem
في أعلى الوسم<script>
:
import ToDoItem from './components/ToDoItem.vue';
-
أضِف الخاصية
components
ضمن كائن المكوِّن ثم أضِف ضمنها المكوِّنToDoItem
لتسجيله.
يجب أن تبدو محتويات الوسم <script>
الآن كما يلي:
import ToDoItem from './components/ToDoItem.vue'; export default { name: 'app', components: { ToDoItem } };
هذه هي الطريقة نفسها التي سُجِّل بها المكوِّن HelloWorld
بواسطة واجهة CLI الخاصة بإطار العمل Vue سابقًا.
يمكنك تصيير المكوِّن ToDoItem
فعليًا في التطبيق من خلال الانتقال إلى العنصر <template>
واستدعائه بوصفه عنصر بالشكل:
<to-do-item></to-do-item>
ولاحظ أنّ اسم ملف المكوِّن وتمثيله في جافاسكربت يكون دائمًا في حالة أحرف باسكال PascalCase مثل ToDoList
، ويكون العنصر المخصّص المكافئ دائمًا في نمط أحرف أسياخ الشواء Kebab-case مثل <to-do-list>
.
-
أنشئ قائمةً غير مرتبة
<ul>
بعد العنصر<h1>
تحتوي على عنصر قائمة واحد<li>
. -
أضِف العنصر
<to-do-item></to-do-item>
ضمن عنصر القائمة.
يجب أن تبدو محتويات العنصر <template>
في الملف App.vue الآن كما يلي:
<div id="app"> <h1>To-Do List</h1> <ul> <li> <to-do-item></to-do-item> </li> </ul> </div>
إذا تحقّقتَ من تطبيقك المُصيَّر مرةً أخرى، فيجب أن ترى الآن العنصر ToDoItem
المُصيَّر الذي يتكون من مربع اختيار وعنوان label
.
إضافة خاصيات للمكونات
لا يزال المكوِّن ToDoItem
غير مفيد للغاية لأنه يمكننا تضمينه مرةً واحدة فقط في الصفحة، إذ يجب أن تكون المعرّفات فريدةً، وليس لدينا طريقة لضبط نص العنوان ولا يُعَدّ ذلك ديناميكيًا.
ما نحتاجه الآن هو حالة المكوِّن التي يمكن تحقيقها من خلال إضافة الخاصيات Props إلى المكوِّن، إذ تشبه الخاصيات مدخلات دالة ما، وتعطي قيمة الخاصية للمكونات حالة أولية تؤثر على عرضها.
تسجيل الخاصيات
هناك طريقتان لتسجيل الخاصيات في Vue هما:
- الطريقة الأولى هي سرد الخاصيات بوصفها مصفوفةً من السلاسل النصية فقط، إذ تقابل كل مدخلة في المصفوفة اسم خاصية.
- الطريقة الثانية هي تعريف الخاصيات بوصفها كائنات، إذ يقابل كل مفتاح اسم الخاصية، كما يسمح سرد الخاصيات بوصفها كائنات بتحديد القيم الافتراضية وتحديد الخاصيات بأنها إجبارية وتطبيق أنواع الكائن الأساسية (أنواع جافاسكربت الأولية تحديدًا)، بالإضافة إلى إجراء تحقق بسيط من صحة الخاصية.
ملاحظة: لا يحدث التحقق من صحة الخاصية إلا في وضع التطوير، لذلك لا يمكنك الاعتماد عليها بصورة صارمة في عملية الإنتاج، كما تُستدعَى دوال التحقق من صحة الخاصية قبل إنشاء نسخة من المكوِّن، لذلك لا يمكنها الوصول إلى حالة المكوِّن أو الخاصيات الأخرى، وسنستخدِم تابع تسجيل الكائن بالنسبة لهذا المكوِّن.
ارجع إلى الملف ToDoItem.vue، ثم أضِف الخاصية props
ضمن كائن التصدير default {}
الذي يحتوي على كائن فارغ، وبعدها أضف ضمن هذا الكائن خاصيتين مع المفتاحين label
و done
، وتذكَّر أنّ قيمة المفتاح label
يجب أن تكون كائنًا مع خاصيتن (أو Props كما يطلق عليها في سياق توفرهما للمكوّنات) وهما:
-
الأولى هي الخاصية
required
التي ستكون لها القيمةtrue
مما يخبر Vue أننا نتوقع أن يكون لكل نسخة من هذا المكوِّن حقل عنوان أو تسميةlabel
، وسيعطي Vue تحذيرًا إذا لم يتضمن المكوِّنToDoItem
على حقل عنوان. -
الثانية هي خاصية النوع
type
. اضبط قيمة هذه الخاصية على نوع جافاسكربتString
(لاحظ الحرف الكبير "S")، وهذا يخبر Vue أننا نتوقع أن تكون قيمة هذه الخاصية سلسلةً نصيةً.
أما بالنسبة للخاصية done
، فأضِف أولًا الحقل default
مع القيمة false
، وهذا يعني أنّ الخاصية done
ستكون لها القيمة false
عند عدم تمريرها إلى المكوِّن ToDoItem
، وضَع في الحسبان أنّ هذا ليس مطلوبًا، إذ نحتاج فقط إلى الحقل default
مع الخاصيات غير المطلوبة، وأضف بعد ذلك حقل النوع type
مع القيمة Boolean
، وهذا يخبر Vue أننا نتوقع أن يكون لخاصية القيمة value النوع المنطقي boolean في جافاسكربت.
يجب أن يبدو كائن المكوِّن الآن كما يلي:
<script> export default { props: { label: { required: true, type: String }, done: { default: false, type: Boolean } } }; </script>
استخدام الخاصيات المسجلة
يمكننا الآن بعد تعريف هذه الخاصيات ضمن كائن المكوِّن استخدام هذه القيم المتغيرة في قالبنا ولنبدأ بإضافة الخاصية label
إلى قالب المكوِّن.
ضع مكان محتويات العنصر <label>
القيمة {{label}}
في عنصر القالب <template>
، إذ تُعَدّ {{}}
صيغة قوالب خاصة في Vue تتيح طباعة نتيجة تعابير جافاسكربت المُعرَّفة في الصنف Class ضمن القالب، بما في ذلك القيم والتوابع، كما يُعرَض المحتوى ضمن {{}}
بوصفه نصًا وليس شيفرة HTML، وبالتالي سنطبع قيمة الخاصية label
في هذه الحالة.
يجب أن يبدو قسم قالب المكوِّن الآن كما يلي:
<template> <div> <input type="checkbox" id="todo-item" /> <label for="todo-item">{{label}}</label> </div> </template>
ارجع إلى متصفحك وسترى عنصر المهام مُصيَّرًا كما كان سابقًا، ولكن بدون العنصر label
، وانتقل إلى أدوات التطوير DevTools في متصفحك وسترى تحذيرًا في الطرفية كما يلي:
[Vue warn]: Missing required prop: "label" found in ---> <ToDoItem> at src/components/ToDoItem.vue <App> at src/App.vue <Root>
يكون هذا بسبب أننا ميّزنا الخاصية label
بوصفها خاصيةً مطلوبةً أو إجباريةً، لكننا لم نعطِ المكوِّن هذه الخاصية مطلقًا، إذ حدّدنا المكان الذي نريد استخدامه ضمن القالب، لكننا لم نمرّره إلى المكوِّن عند استدعائه، إذًا لنصلح ذلك.
أضف الخاصية label
إلى المكوِّن <to-do-item>
في الملف App.vue مثل سمة HTML العادية تمامًا:
<to-do-item label="My ToDo Item"></to-do-item>
سترى الآن العنصر label
في تطبيقك دون تحذير في الطرفية مرةً أخرى.
كائن الخاصية data في Vue
إذا عدّلتَ قيمة الخاصية label
المُمرَّرة إلى المكون <to-do-item>
في تطبيقك، فيجب أن تراها مُحدَّثةً.
لدينا الآن مربع اختيار مع عنصر label
قابل للتحديث، ولكننا لا نطبّق حاليًا أيّ شيء باستخدام الخاصية done
، إذ يمكننا تحديد مربعات الاختيار في واجهة المستخدِم، ولكن لا يوجد مكان في التطبيق نسجل فيه ما إذا كان عنصر المهام المطلوب قد اكتمل فعليًا أم لا.
يمكنك تحقيق ذلك من خلال ربط الخاصية done
الخاصة بالمكوِّن مع السمة checked
في العنصر <input>
، بحيث يمكن أن تكون بمثابة سجل لما إذا كان مربع الاختيار محددًا أم لا، إذ يجب أن تعمل الخاصيات بوصفها رابط بيانات أحادي الاتجاه، ويجب ألّا يغير المكوِّن قيمة خاصياته أبدًا، إذ يمكن أن تجعل خاصيات تعديل المكونات تنقيح الأخطاء تحديًا، فإذا مُرِّرت قيمةً إلى عدة أبناء، فيمكن أن يكون تتبُّع مصدر تغييرات هذه القيمة أمرًا صعبًا، كما يمكن أن يؤدي تغيير الخاصيات إلى إعادة تصيير المكوّنات، لذا فسيؤدي تغيّر خاصيات المكوِّن إلى إعادة تصييره، مما يؤدي بدوره إلى حدوث التغيّر مرةً أخرى.
يمكننا حل هذه المشكلة من خلال إدارة الحالة done
باستخدام الخاصية data
في Vue، إذ تُعَدّ الخاصية data
المكان الذي يمكنك من خلاله إدارة حالة المكوِّن المحلية، فهي توجد ضمن كائن المكوِّن جنبًا إلى جنب مع الخاصية props
ولها البنية التالية:
data() { return { key: value } }
لاحظ أنّ الخاصية data
هي دالة للحفاظ على قيم البيانات فريدة لكل نسخة من المكوِّن في وقت التشغيل، إذ تُستدعَى الدالة بصورة منفصلة لكل نسخة من المكوِّن. فإذا عرّفتَ الخاصية data
بوصفها كائن فقط، فستشترك جميع نسخ هذا المكوِّن في القيم نفسها، وهذا أحد الآثار الجانبية التي لا نريدها للطريقة التي يسجِّل بها Vue المكوّنات، كما يمكنك استخدام this
للوصول إلى خاصيات المكوّن والخاصيات الأخرى من data
وسنرى مثالًا عن ذلك لاحقًا.
ملاحظة: بما أن الطريقة التي يعمل بها this
يمكن استخدامها في الدوال السهمية Arrow Function أو الارتباط بسياق الآباء، فلن تتمكن من الوصول إلى أيّ من السمات الضرورية من data
إذا استخدمتَ هذه الدالة، لذلك لا تستخدِمها مع الخاصية data
.
لنضِف الخاصية data
إلى المكوِّن ToDoItem
، إذ سيعيد ذلك كائنًا يحتوي على خاصية واحدة سنسميها isDone
التي تكون قيمتها this.done
.
عدّل كائن المكوِّن كما يلي:
export default { props: { label: { required: true, type: String }, done: { default: false, type: Boolean } }, data() { return { isDone: this.done }; } };
يربط Vue جميع خاصياتك بنسخة المكوِّن مباشرةً، لذلك لا يتعين علينا استدعاء this.props.done
، ويربط السمات الأخرى مثل data
و methods
و computed
وغيرها مباشرةً بنسخة المكوِّن لجعلها متاحةً لقالبك، لكن يجب الاحتفاظ بالمفاتيح فريدة لهذه السمات، وهذا هو السبب في أننا أطلقنا على سمة data
الاسم isDone
عوضًا عن done
.
يجب الآن ربط الخاصية isDone
بالمكوِّن، إذ يملك Vue بنية صيغة لربط تعابير جافاسكربت بعناصر ومكونات HTML بطريقة مشابهة لكيفية استخدام Vue لتعابير {{}}
لعرض تعابير جافاسكربت ضمن القوالب، وهذه الصيغة هي v-bind
التي تبدو كما يلي:
v-bind:attribute="expression"
وبالتالي ستسبق العبارة v-bind:
أيّ سمة أو خاصية تريد ربطها، ويمكنك استخدام اختصار للخاصية v-bind
في أغلب الأحيان، وهذا الاختصار هو استخدام تقطتين قبل السمة أو الخاصية، لذلك تعمل العبارة :attribute="expression"
بطريقة مشابهة للعبارة v-bind:attribute="expression"
، لذلك يمكننا استخدام v-bind
لربط الخاصية isDone
مع السمة checked
في العنصر <input>
في حالة استخدام مربع اختيار ضمن المكوِّن ToDoItem
، كما أنّ الأمرَين التاليَين متكافئان:
<input type="checkbox" id="todo-item" v-bind:checked="isDone" /> <input type="checkbox" id="todo-item" :checked="isDone" />
أنت حر في استخدام النمط الذي تريده، ولكن يُفضَّل الحفاظ على كل شيء متسقًا قدر الإمكان، وبما أنّ استخدام صيغة الاختصار أكثر شيوعًا، فسنلتزم بهذا النمط في هذا المقال.
عدّل العنصر <input>
الآن ليشمل :checked="isDone"
.
اختبر مكوِّنك عن طريق تمرير :done="true"
إلى استدعاء المكوِّن ToDoItem
في الملف App.vue، ولاحظ أنك تحتاج إلى استخدام صيغة v-bind
، لأنّ القيمة true
ستُمرَّر بوصفها سلسلةً نصيةً بخلاف ذلك، كما يجب تحديد مربع الاختيار المعروض.
<template> <div id="app"> <h1>My To-Do List</h1> <ul> <li> <to-do-item label="My ToDo Item" :done="true"></to-do-item> </li> </ul> </div> </template>
حاول تغيير القيمة true
إلى false
، ثم أعِد تحميل تطبيقك لترى كيفية تغيّر الحالة.
إعطاء المهام معرفا فريدا
رائع، أصبح لدينا الآن مربع اختيار يعمل بنجاح، إذ يمكننا ضبط الحالة برمجيًا، لكن يمكننا حاليًا إضافة مكوِّن ToDoList
واحد فقط إلى الصفحة لأن المعرّف id
ثابت، مما يؤدي إلى حدوث أخطاء في التقنية المساعدة لأننا بحاجة هذا المعرّف لربط العناوين أو التسميات إلى مربعات الاختيار المقابلة لها بصورة صحيحة، ويمكن إصلاح هذا الخطأ من خلال ضبط المعرّف id
برمجيًا في بيانات المكوِّن.
يمكننا استخدام التابع uniqueid()
الخاص بحزمة Lodash للمساعدة في إبقاء الفهرس فريدًا، إذ تصدِّر هذه الحزمة دالةً تأخذ سلسلةً نصيةً وتضيف عددًا صحيحًا فريدًا إلى نهاية البادئة، وسيكون هذا كافيًا لإبقاء معرِّفات المكوّنات فريدة.
يجب إضافة هذه الحزمة إلى مشروعنا باستخدام npm، لذا أوقف خادمك وأدخِل الأمر التالي في طرفيتك:
npm install --save lodash.uniqueid
ملاحظة: إذا أردت استخدام yarn، فيمكنك كتابة الأمر yarn add lodash.uniqueid
.
يمكننا الآن استيراد هذه الحزمة إلى المكوِّن ToDoItem
، لذا أضِف السطر التالي قبل العنصر <script>
في الملف ToDoItem.vue:
import uniqueId from 'lodash.uniqueid';
أضِف بعد ذلك الحقل id
إلى الخاصية data
بحيث يبدو كائن المكوِّن بالصورة التالية، إذ يعيد التابع uniqueId()
البادئة todo-
مع سلسلة نصية فريدة ملحقَة بها:
import uniqueId from 'lodash.uniqueid'; export default { props: { label: { required: true, type: String }, done: { default: false, type: Boolean } }, data() { return { isDone: this.done, id: uniqueId('todo-') }; } };
اربط بعد ذلك المعرِّف id
مع كل سمة id
الخاصة بمربع الاختيار والسمة for
الخاصة بالعنوان أو التسمية، وعدِّل السمات id
و for
الحالية كما يلي:
<template> <div> <input type="checkbox" :id="id" :checked="isDone" /> <label :for="id">{{label}}</label> </div> </template>
الخلاصة
لدينا حتى الآن المكوِّن ToDoItem
الذي يعمل بنجاح، ويمكنه تمرير عنوان أو تسمية لعرضها، كما سيخزّن حالته المحدَّدة، وسيُصيَّر مع معرِّف id
فريد في كل مرة يُستدعَى فيها، كما يمكنك التحقق مما إذا كانت المعرّفات الفريدة تعمل عن طريق إضافة المزيد من استدعاءات المكونات <to-do-item>
مؤقتًا في الملف App.vue ثم التحقق من خرجها المُصيَّر باستخدام أدوات التطوير DevTools في متصفحك.
نحن الآن جاهزون لإضافة عدة مكونات ToDoItem
إلى تطبيقنا، إذ سنتعلّم في المقال التالي كيفية إضافة مجموعة من بيانات عناصر المهام إلى المكوِّن App.vue
، والتي سنكرّرها ونعرضها ضمن المكوّنات ToDoItem
باستخدام الموجّه v-for
.
ترجمة -وبتصرّف- للمقال Creating our first Vue component.
اقرأ أيضًا
- المقال السابق: مدخل إلى إطار العمل Vue.js
- مدخل إلى التعامل مع المكونات في Vue.js
- التعامل مع دخل المستخدم عن طريق نماذج الإدخال في Vue.js
- النسخة الكاملة لكتاب أساسيات إطار العمل Vue.js
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.