Skip to content

تصيير القوائم

v-for

يمكنك استخدام السمة الموجهة v-for لتصيير قائمة من العناصر بناءً على مصفوفة. تتطلب السمة v-for صيغة خاصة على شكل item in items، حيث items هو مصدر بيانات المصفوفة و item هو الاسم المستعار لعنصر المصفوفة الذي يتكرر في العملية:

js
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
js
data() {
  return {
    items: [{ 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' }])
js
data() {
  return {
    parentMessage: 'الأب',
    items: [{ message: 'Foo' }, { message: 'Bar' }]
  }
}
template
<li v-for="(item, index) in items">
  {{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
  • الأب - 0 - Foo
  • الأب - 1 - Bar
  • النطاق المتغير لـ 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'
    })
    js
    data() {
      return {
        myObject: {
          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، وتمرير بيانات مختلفة إلى كل نسخة.

    اطلع على هذا المثال لقائمة مهام بسيطة لترى كيفية تصيير قائمة من المكونات باستخدام 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/))
    js
    this.items = this.items.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)
    })
    js
    data() {
      return {
        numbers: [1, 2, 3, 4, 5]
      }
    },
    computed: {
      evenNumbers() {
        return this.numbers.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)
    }
    js
    data() {
      return {
        sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
      }
    },
    methods: {
      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()
    تصيير القوائم has loaded