تصيير القوائم
v-for
يمكنك استخدام السمة الموجهة v-for
لتصيير قائمة من العناصر بناءً على مصفوفة. تتطلب السمة v-for
صيغة خاصة على شكل item in items
، حيث items
هو مصدر بيانات المصفوفة و item
هو الاسم المستعار لعنصر المصفوفة الذي يتكرر في العملية:
js
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
template
<li v-for="item in items">
{{ item.message }}
</li>
في داخل نطاق v-for
، تعبيرات القالب يمكنها الوصول إلى جميع خاصيات النطاق الأب. بالإضافة إلى ذلك، يدعم v-for
أيضًا اسم بديل اختياري ثان يعمل كمؤشر للعنصر الحالي :
js
const parentMessage = ref('Parent')
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
template
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
النطاق المتغير لـ v-for
مشابه لشيفرة الـJavaScript التالية:
js
const parentMessage = 'Parent'
const items = [
/* ... */
]
items.forEach((item, index) => {
// لديها وصول إلى النطاق الخارجي `parentMessage` لكن
// `item` و `index` متوفرة فقط هنا
console.log(parentMessage, item.message, index)
})
تجدر الإشارة إلى أن قيمة v-for
تتطابق مع وسائط دالة رد النداء لـ forEach
. في الواقع ، يمكنك استخدام التفكيك على مسمى عنصر v-for
مماثلًا لتفكيك معطيات الدالة :
template
<li v-for="{ message } in items">
{{ message }}
</li>
<!-- مع الاسم البديل للمؤشر -->
<li v-for="({ message }, index) in items">
{{ message }} {{ index }}
</li>
بالنسبة لـ v-for
المتداخلة، يعمل النطاق أيضًا مثل حالة الدوال المتداخلة. لدى كل نطاق v-for
إمكانية الوصول إلى النطاقات الأب :
template
<li v-for="item in items">
<span v-for="childItem in item.children">
{{ item.message }} {{ childItem }}
</span>
</li>
يمكنك أيضا استخدام of
كفاصل بدلا من in
، بحيث أنها أقرب الى صيغة المُكرِّرات في الـJavascript :
template
<div v-for="item of items"></div>
v-for
مع كائن
يمكنك أيضا استخدام v-for
للمرور عبر خاصيات الكائن. سيكون ترتيب المرور على أساس نتيجة استدعاء الدالة ()Object.keys
على الكائن :
js
const myObject = reactive({
title: 'كيف تصير القوائم في Vue',
author: 'ابراهيم بوسجرة',
publishedAt: '2016-04-10'
})
template
<ul>
<li v-for="value in myObject">
{{ value }}
</li>
</ul>
يمكنك أيضا توفير اسم بديل لاسم الخاصية (كما هو متعارف عليه بالمفتاح):
template
<li v-for="(value, key) in myObject">
{{ key }}: {{ value }}
</li>
و آخر للمؤشر:
template
<li v-for="(value, key, index) in myObject">
{{ index }}. {{ key }}: {{ value }}
</li>
v-for
مع مدى
v-for
يمكنها أيضا أخذ عدد صحيح كمدى. في هذه الحالة سيكرر العنصر مرات كثيرة ، وفقا لمدى من 1 إلى n
.
template
<span v-for="n in 10">{{ n }}</span>
تجدر الإشارة إلى أن n
تبدأ بقيمة أولية من 1
بدلا من 0
.
v-for
على <template>
على غرار استخدام القالب مع v-if
، يمكنك أيضا استخدام عنصر الـ<template>
مع v-for
لتقديم كتلة من عناصر متعددة. على سبيل المثال :
template
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for
مع v-if
ملاحظة
لا يوصى باستخدام v-if
و v-for
على نفس العنصر بسبب الأولوية المضمنة لـv-if
. اطلع على دليل الأسلوب للحصول على التفاصيل.
عندما يتواجدان على نفس العنصر ، فإن v-if
لها أولوية أعلى من v-for
. وهذا يعني أن شرط v-if
لن يكون قادرا على الوصول إلى المتغيرات من نطاق v-for
:
template
<!--
سيطلق خطأ لأن الخاصية "todo"
غير معرفة على النسخة.
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
يمكن اصلاح هذا من خلال نقل v-for
إلى علامة <template>
(وهو أيضا أكثر وضوحا):
template
<template v-for="todo in todos">
<li v-if="!todo.isComplete">
{{ todo.name }}
</li>
</template>
الحفاظ على الحالة مع key
عندما تقوم Vue بتحديث قائمة العناصر المصيَّرة باستخدام v-for
، فإنه بشكل افتراضي تستخدم استراتيجية "التصحيح في المكان". إذا تغير ترتيب عناصر البيانات ، بدلاً من نقل عناصر DOM لكي تُطابِق ترتيب عناصر البيانات ، فستقوم Vue بتصحيح كل عنصر في المكان وتتأكد من أنه يعكس ما يجب تصييره في مكان الموافق لذلك المؤشر.
هذا الوضع الافتراضي فعال ، ولكن مناسب فقط عندما لا يعتمد تصيير قائمة العناصر على حالة مكون ابن أو حالة DOM مؤقتة (على سبيل المثال قيم الإدخال في النموذج).
لتعطي Vue تلميحًا لكي يتمكن من تتبع هوية كل عنصر، وبالتالي إعادة استخدام و ترتيب العناصر الحالية، فإنك بحاجة إلى توفير سمة key
وحيدة لكل عنصر:
template
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
عند استخدام <template v-for>
، يجب وضع key
على العنصر المُغلِّف <template>
:
template
<template v-for="todo in todos" :key="todo.name">
<li>{{ todo.name }}</li>
</template>
ملاحظة
key
هنا هو سمة خاصة تربط مع v-bind
. لا ينبغي الخلط بينها وبين متغير الخاصية المفتاحية عند استخدام v-for
مع كائن.
يُوصى بتوفير سمة key
مع v-for
في كل الأحوال الممكنة ، ما لم يكن المحتوى DOM المصيَّر بسيطًا (أي يحتوي على عناصر مكونات أو عناصر DOM ذات حالة) ، أو إذا كنت تعتمد على السلوك الافتراضي قصدا لتحسين الأداء.
الربط بـ key
يتوقع قيمًا أولية - أي سلاسل نصية وأرقام. لا تستخدم الكائنات كمفاتيح v-for
. لمزيد من المعلومات حول سمة key
، يرجى الاطلاع على وثائق واجهة برمجة التطبيقات key
.
v-for
مع مكون
هذا القسم يفترض أن تكون لك معرفة يالمكونات. لا تتردد في تخطيه والعودة إليه لاحقًا.
يمكنك مباشرة استخدام v-for
على المكون ، مثل أي عنصر عادي (لا تنسى توفير key
) :
template
<MyComponent v-for="item in items" :key="item.id" />
مع ذلك، لن يقوم هذا بتمرير أي بيانات تلقائيًا إلى المكون ، لأن المكونات لها نطاقات معزولة خاصة بها. لتمرير البيانات المتكررة إلى المكون ، يجب استخدام الخاصيات :
template
<MyComponent
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
/>
السبب في عدم تمرير item
تلقائيًا إلى المكون هو أن ذلك يجعل المكون مرتبطًا بشكل كبير بكيفية عمل v-for
. توضيح مصدر بيانات المكون يجعله قابل لإعادة الاستخدام في وضعيات أخرى.
اطلع على هذا المثال لقائمة مهام بسيطة لترى كيفية تصيير قائمة من المكونات باستخدام v-for
، وتمرير بيانات مختلفة إلى كل نسخة.
كشف تغير المصفوفة
توابع التعديل
Vue قادرة على كشف التغيرات عندما تُستدعى توابع تعديل المصفوفة التفاعلية وتشغيل التحديثات اللازمة. هذه هي توابع التعديل :
()push
()pop
()shift
()unshift
()splice
()sort
()reverse
استبدال مصفوفة
توابع التعديل، كما يشير الاسم، تعدل المصفوفة الأصلية التي تُستدعى عليها. بالمقابل، هناك أيضًا توابع غير تعديلية ، على سبيل المثال ، ()filter
، ()concat
و ()slice
، والتي لا تعدل المصفوفة الأصلية ولكن تعيد دائمًا مصفوفة جديدة. عند العمل مع توابع غير تعديلية ، يجب أن نستبدل المصفوفة القديمة بالجديدة :
js
// `items` هو مرجع مع مصفوفة كقيمة
items.value = items.value.filter((item) => item.message.match(/Foo/))
بما تتسائل عما إذا كان سيؤدي ذلك إلى تخلي Vue عن محتوى الـDOM الموجود وإعادة تصيير قائمة كاملة - لحسن الحظ، هذا ليس هو الحال. تنفذ Vue بعض الاستدلالات الذكية لتحسين إعادة استخدام عنصر DOM ، لذلك استبدال مصفوفة بمصفوفة أخرى تحتوي على كائنات متداخلة هي عملية فعالة جدًا.
عرض النتائج المنقحة / المصنفة
بعض الأحيان نريد عرض إصدار منقح أو مصنف من مصفوفة دون تعديلها أو إعادة تعيين البيانات الأصلية. في هذه الحالة ، يمكنك إنشاء خاصية محسوبة تعيد المصفوفة المنقحة أو المصنفة.
على سبيل المثال:
js
const numbers = ref([1, 2, 3, 4, 5])
const evenNumbers = computed(() => {
return numbers.value.filter((n) => n % 2 === 0)
})
template
<li v-for="n in evenNumbers">{{ n }}</li>
في الحالات التي لا يمكن فيها استخدام خاصيات محسوبة (على سبيل المثال ، داخل حلقات v-for
المتداخلة) ، يمكنك استخدام تابع أو دالة:
js
const sets = ref([
[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]
])
function even(numbers) {
return numbers.filter((number) => number % 2 === 0)
}
template
<ul v-for="numbers in sets">
<li v-for="n in even(numbers)">{{ n }}</li>
</ul>
كن حذرا عند استخدام ()reverse
و ()sort
داخل خاصية محسوبة! هاتين الدالتين ستعدلان المصفوفة الأصلية، وهذا يجب تجنبه في محصلات الخاصية المحسوبة. قم بإنشاء نسخة من المصفوفة الأصلية قبل استدعاءهما :
diff
- return numbers.reverse()
+ return [...numbers].reverse()