رهگیری عناصر در v-for

Tracking Elements in v-for

31 شهریور 1399
Vue.JS 2: رهگیری عناصر در v-for

در قسمت قبل با کلیت v-for آشنا شدیم و انواع روش های استفاده از آن را دیدیم اما هنوز نکته کوچکی باقی مانده است. پس از بررسی این نکته، وارد مبحث رهگیری عناصر در v-for شده و این فصل را نیز به پایان می رسانیم. فرض کنید می خواهم تنها لیستی از اعداد را نمایش بدهیم (مثلا از 1 تا 10). برای این کار می توانیم به شکل زیر عمل کنیم:

    <span v-for="n in 10"></span>

N نام انتخابی من برای هر مقداری است که قرار است دریافت کنیم (هر عدد از 1 تا 10). توجه داشته باشید که 10 قاعدتا نمی تواند نام یکی از خصوصیات من در Data باشد بنابراین زمانی که Vue چنین کدی را می بینید در بازه مشخص شده از اعداد طبیعی (صحیح مثبت) گردش می کند. مثلا 10 یعنی از 1 تا 10. حالا می توان گفت:

    <span v-for="n in 10"> {{ n }} </span>

با انجام این کار خروجی زیر را خواهید داشت:

12345678910

توجه کنید که هر عدد درون یک span قرار می گیرد و حالت طبیعی Span ها نیز inline است بنابراین در کنار هم قرار خواهند گرفت.

رهگیری عناصر در V-for

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

<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
    <ul>
        <li v-for="(ingredient, i) in ingredients">{{ingredient}} ({{i}})</li>
    </ul>
    <button @click="ingredients.push('spices')">Add New</button>
    <hr>
    <ul>
        <li v-for="person in persons">
            <div v-for="(value, key, index) in person"> {{key}}: {{ value }} ({{index}}) </div>
        </li>
    </ul>
    <span v-for="n in 10"> {{ n }} </span>
    <hr>
    <template v-for="(ingredient, index) in ingredients">
        <h1>{{ ingredient }} </h1>
        <p>{{ index}} </p>
    </template>
</div>

با دقت به این کد متوجه می شوید که من یک دکمه جدید به آن اضافه کرده ام که هنگام کلیک شدن، عبارت spices را به آرایه جدید اضافه می کند (تابع push یک تابع ساده جاوا اسکریپتی است و باید آن را بشناسید). حالا چرا این کار را کرده ام؟ شما باید به عنوان برنامه نویس از پشت صحنه کدهای خود مطلع باشید.

زمانی که از حلقه v-for استفاده کرده باشیم اما در آیتم های ما تغییری ایجاد شود چه اتفاقی می افتد؟ مثلا ما کدهای بالا را در مرورگر نمایش می دهیم و خروجی اش را به شکل زیر می بینیم:

  • meat (0)
  • fruit (1)
  • cookies (2)

حالا اگر یک بار روی دکمه Add New کلیک کنیم خروجی ما به شکل زیر تغییر می کند:

  • meat (0)
  • fruit (1)
  • cookies (2)
  • spices (3)

این رفتار قسمت ظاهری کدهای ما می باشد که هدف نهایی ما است اما نحوه اعمال این تغییرات و پشت صحنه کدها بسیار مهم هستند. در این رابطه چند نکته خدمتتان عرض می کنم:

اولا رهگیری تغییرات روی یک آرایه (مثل push) کمی سخت است چرا که با push آرایه جدیدی ساخته نمی شود و از آنجایی که آرایه ها reference type هستند، pointer آن ها به تایپ مورد نظر تغییری نکرده است (فقط مقدارِ درون مموری تغییر می کند). بنابراین برای تشخیص تغییرات در آرایه ها، باید مقدار آن ها در مموری را زیر نظر بگیرید و Vue نیز این کار را به صورت خودکار برای ما انجام می دهد. البته در صورتی که به آن بگوییم چنین کاری را انجام دهد.

دوما حالا که Vue تغییرات مقدار را زیر نظر دارد برای ایجاد به روز رسانی ها و ویرایش های یک آرایه در لیست، موقعیت آن تغییر را به روز رسانی می کند. به طور مثال اگر با استفاده از two-way-binding یا هر روش دیگری، عنصر دوم یک آرایه را تغییر بدهید Vue متوجه شده و آن را به روز رسانی می کند. توجه کنید که Vue به عنصر جدیدی که ساخته شده است اهمیت نمی دهد و فقط آن را در موقعیت عنصر دوم قرار می دهد. مثلا اگر به جای fruit کلمه lemon را در لیست قرار دهیم، Vue اهمیتی به مقدار lemon نمی دهد (مقدار lemon فقط وسیله ای برای تشخیص تغییرات است) بنابراین fruit را حذف کرده و lemon را به جایش قرار خواهد داد. در اکثر اوقات این مسئله مشکل زا نیست اما اگر می خواهید Vue علاوه بر موقعیت مکانی یک عنصر، همیشه از مقدار آن نیز با خبر باشد باید یک key خاص را برایش تعیین کنید.

اگر با فریم ورک هایی مانند react کار کرده باشید متوجه منظور من می شوید. به طور مثال به کد زیر نگاه کنید:

    <ul>
        <li v-for="(ingredient, i) in ingredients">{{ingredient}} ({{i}})</li>
    </ul>

اگر بخواهیم برای این کد یک key تعریف کنیم به شکل زیر عمل می کنیم:

    <ul>
        <li v-for="(ingredient, i) in ingredients" :key="ingredient">{{ingredient}} ({{i}})</li>
    </ul>

اگر یادتان باشد علامت دو نقطه (:) حالت خلاصه شده v-bind است. مقداری که به key پاس داده می شود باید حتما یکتا و خاص باشد. در نگاه اول افراد بسیاری همان index را پاس می دهند اما index از خود لیست تولید می شود و ممکن است همیشه طبق انتظار ما کار نکند. بهترین کار این است که مقداری کاملا یکتا را پیدا کرده و آن را به key بدهید. مثلا از آنجایی که من می دانم هر کدام از ingredient ها فقط و فقط یک بار در لیست من حضور خواهند داشت (هیچ وقت دو بار meat یا fruit نخواهیم داشت)، می توان گفت ingredient خودش یک مقدار یکتاست.

اگر کد بالا را دوباره اجرا کنیم، هیچ تفاوتی را در ظاهر برنامه مشاهده نمی کنیم اما Vue در پشت صحنه این کدها نه تنها مکان عنصر جدید را ذخیره می کند، بلکه خود عنصر را نیز برای خودش نگه می دارد. بر این اساس اگر قرار باشد Vue این عناصر را دوباره ترتیب دهی کند (یا هر ویرایشی شبیه به آن)، خود آن عنصر را (تمام عنصر را) برداشته و جا به جا می کند نه اینکه مقدار خاصی را (مثلا meat را) در موقعیت خاصی (مثلا عنصر دوم) overwrite کند.

حالا چرا این مبحث را برای شما توضیح دادم؟ در توسعه برنامه های واقعی و بزرگتر، ممکن است به باگ های عجیبی در رابطه با لیست هایتان برخورد کنید. مثلا ممکن است برخی از عناصر در مکان اشتباهی به روز رسانی شوند و ترتیبشان به هم بریزد. اگر با چنین باگ هایی روبرو شدید، معمولا با اضافه کردن key مشکل حل می شود.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش رایگان Vue js از صفر تا صد توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.