سلام دوستان. توی فریم‌ورک ویوو اگه یک لیست (آرایه یا آبجکت) داشته باشیم و بخوایم اون رو توی قسمت View نمایش بدیم، از دستور v-for استفاده می‌کنیم. استفاده از این دستور بصورت زیر هست:

<div id="app">

  <p v-for="item in items">
    {{ item }}
  </p>

   <!-- or -->
  <ul>
    <li v-for="user in users">
      {{ user.name }} / {{ user.age }}
    </li>
  </ul>

</div>
const app = new Vue({
  el: '#app',
  data:{
    items: [ 1, 2, 3 ],
    users: [
      { name: 'Evan', age: 34 },
      { name: 'Sarah', age: 27 },
    ]
  }
});

فرمت این دستور بصورت v-for="item in items" هست که توی اون items یک آرایه قابل پیمایش هست که توی قسمت data یا بطور کلی توی برنامه تعریف شده و قابل دسترسی هست. item هم یک اسم دلخواه برای المنتی از items هست که توی پیمایش فعلی اون رو داریم.

جالبه که بدونیم حلقه for...of هم توی v-for کار می‌کنه. ()

 

دستور v-for روی template

وقتی v-for رو یک المنت مثل تگ div اعمال میشه، خود اون المنت به همراه محتویات اون تکرار میشن:

<div v-for="user in users">
  {{ user.name }}
</div>

که خروجی کد بالا بصورت زیر هست:

<div id="app">
  <div>Evan</div>
  <div>Sarah</div>
</div>

اگه شرایطی داریم که می‌خوایم فقط محتویات المنت نمایش داده بشن، بجای div از template استفاده می‌کنیم:

<template v-for="user in users">
  {{ user.name }}
</template>

که خروجی این کد بصورت زیر هست:

<div id="app">
  Evan
  Sarah
</div>

 

v-for و آبجکت‌ها

آبجکت‌ها یا بطور کلی رو می‌تونیم توی v-for استفاده کنیم. آبجکت‌های جاوااسکریپت قابل پیمایش هستن. آبجکت user رو در نظر بگیرین:

const app = new Vue({
  el: '#app',
  data:{
    user: {
      name: 'Jack',
      age: 19,
      state: 'Texas'
    }
  }
});

اگه از دستور v-for برای نمایش user استفاده کنیم:

<div id="app">
  <div v-for="info in user">
    {{ info }}
  </div>
</div>

خروجی بصورت زیر خواهد بود:

Jack
19
Texas 

همونطور که می‌بینیم key های آبجکت رو نداریم. برای دسترسی به key های آبجکت باید v-for رو بصورت زیر بنویسیم:

<div id="app">
  <div v-for="(info, key) in user">
    {{ key }}: {{ info }}
  </div>
</div>

key هم مثل info یک اسم دلخواه هست که شامل key آبجکت میشه. خروجی کد بالا بصورت زیر هست:

name: Jack
age: 19
state: Texas 

اگه شماره index رو می‌خوایم، پارامتر سوم رو هم به v-for اضافه می‌کنیم:

<div v-for="(info, key, index) in user">
 {{ index }} - {{ key }}: {{ info }}
</div>

 شماره index از صفر شروع میشه و با هر بار تکرار حلقه، یک واحد به اون اضافه میشه:

0 - name: Jack
1 - age: 19
2 - state: Texas 

 

حلقه‌ی v-for می‌تونه بجای پیماش روی آرایه‌ها، یک عدد بگیره تا به اندازه این عدد تکرار انجام بشه:

<span v-for="i in 7">
  {{ i }}
</span>
1 2 3 4 5 6 7

 

v-for و key

قسمت Result کد زیر رو ببینید. می‌خوایم وقتی روی دکمه‌ Delete کلیک شد، آیتمی که توسط v-for رندر شده حذف بشه:

 

حالا ورودی‌ها رو با مقدارهای مختلف پر کنین. وقتی روی Delete کلیک می‌کنیم، اتفاق غیرمنتظره اینه که آیتم‌ها از آخر حذف میشن. با اینکه توی کد مشخص شده که کدوم index حذف بشه.

چرا این اتفاق می‌افته؟ 🤔 چون در حالت پیشفرض المنت‌هایی که توسط v-for رندر میشن، هویت و شناسه‌ی معلومی ندارن و وقتی بروزرسانی توی آیتم‌ها صورت می‌گیره، ویوو تلاشی برای هماهنگ کردن ترتیب نمایش المنت‌ها انجام نمیده. برای حل این مسئله، کنار دستور v-for  از key استفاده می‌کنیم:

<div v-for="(item, index) in items" :key="item.id">

همونطور که می‌بینیم با اضافه شدن key ترتیب‌ها رعایت میشن.

 

فیلتر کردن نمایش اطلاعات

فرض کنیم آرایه‌ای از اعداد داریم و می‌خوایم فقط اونهایی رو نشون بدیم که زوج هستن:

<div id="app">
  <div v-for="number in numbers">
    <span v-if="number % 2 == 0">{{ number }}</span>
  </div>
</div>
const app = new Vue({
  el: '#app',
  data:{
    numbers: [1, 2, 3, 4]
  }
});

کد بالا به درستی کار می‌کنه اما بهینه نیست. چون پیمایش داره رو اعداد فرد هم صورت می‌گیره و ما فیلتر رو توی قسمت View داریم اعمال می‌کنیم. همچنین شرایط و فیلترکردن همیشه به همین سادگی نیست و گاها باید محاسبات پیچیده‌تری انجام بگیره. برای حل این مسئله می‌تونیم از یک استفاده کنیم:

const app = new Vue({
  el: '#app',
  data:{
    numbers: [1, 2, 3, 4]
  },
  computed: {
    evenNumbers() {
      return this.numbers.filter(num => {
        return num % 2 === 0;
      });
    }
  }
});
<div id="app">
  <div v-for="number in evenNumbers">
    <span>{{ number }}</span>
  </div>
</div>

همونطور که می‌بینیم دیگه لازم نیست توی قسمت View منطق و محاسبات بنویسیم.

همچنین میشه از هم استفاده کرد. از خوبی‌های استفاده از متد اینه که می‌تونیم اعداد دلخواه پاس بدیم:

const app = new Vue({
  el: '#app',
  methods: {
    even(numbers) {
      return numbers.filter(number => {
        return number % 2 === 0;
      });
    }
  }
});
<div id="app">
  <div v-for="number in even([1, 2, 3, 4])">
    <span>{{ number }}</span>
  </div>
</div>

 

خب دوستان این قسمت هم به پایان رسید. منتظر قسمت‌های بعدی باشین. روزتون خوش ✌️

منابعی که برای این پست استفاده کردم: