MATIN MOLKARA
SERIES: JavaScript — PART 91 OF 108

91- آموزش جاوااسکریپت | پروژه عملی: قسمت 4 از 12- نمایش آیتم‌ها در رابط کاربری با استفاده از Item Controller و UI Controller

در این بخش، متد getItems را در Item Controller می‌سازیم، داده‌ها را هنگام راه‌اندازی برنامه دریافت می‌کنیم و با متد populateItemList آن‌ها را در رابط کاربری نمایش می‌دهیم. همچنین برای مدیریت بهتر سلکتورها، آبجکت UISelectors را تعریف می‌کنیم.

در بخش قبل، کنترلرهای اصلی برنامه را ایجاد کردیم و ساختار داده یا state اولیه برنامه را داخل Item Controller قرار دادیم.

در این بخش، هدف ما این است که آیتم‌های موجود در داده‌ها را دریافت کنیم و آن‌ها را داخل لیست رابط کاربری نمایش دهیم.
فعلاً این داده‌ها به‌صورت hard-coded داخل برنامه قرار دارند، اما در ادامه می‌توانند از Local Storage یا حتی یک API خارجی دریافت شوند.


دریافت آیتم‌ها از Item Controller

اولین قدم این است که یک متد عمومی در Item Controller بسازیم تا آیتم‌ها را از ساختار داده برگرداند.

کد

// Item Controller
const ItemCtrl = (function () {
  const Item = function (id, name, calories) {
    this.id = id;
    this.name = name;
    this.calories = calories;
  };

  const data = {
    items: [
      { id: 0, name: 'Steak Dinner', calories: 1200 },
      { id: 1, name: 'Cookie', calories: 400 },
      { id: 2, name: 'Eggs', calories: 300 }
    ],
    currentItem: null,
    totalCalories: 0
  };

  return {
    getItems: function () {
      return data.items;
    }
  };
})();

توضیح

در اینجا متد getItems فقط آرایه items را از آبجکت data برمی‌گرداند.
به این شکل، داده‌های داخلی ماژول همچنان خصوصی باقی می‌مانند و فقط از طریق متدهای عمومی به آن‌ها دسترسی داریم.


تست متد getItems

بعد از تعریف این متد، می‌توانیم آن را در مرورگر یا داخل برنامه فراخوانی کنیم تا مطمئن شویم داده‌ها به‌درستی برگردانده می‌شوند.

کد

console.log(ItemCtrl.getItems());

اگر همه چیز درست باشد، آرایه آیتم‌ها در کنسول نمایش داده می‌شود.


دریافت آیتم‌ها هنگام راه‌اندازی برنامه

حالا باید این داده‌ها را هنگام اجرای اولیه برنامه دریافت کنیم. این کار را داخل متد init در App Controller انجام می‌دهیم.

کد

// App Controller
const App = (function (ItemCtrl, UICtrl) {
  return {
    init: function () {
      // دریافت آیتم‌ها از ساختار داده
      const items = ItemCtrl.getItems();

      console.log(items);
    }
  };
})(ItemCtrl, UICtrl);

App.init();

توضیح

در اینجا با اجرای برنامه:

  • آیتم‌ها از Item Controller گرفته می‌شوند
  • داخل متغیر items قرار می‌گیرند
  • برای تست، در کنسول نمایش داده می‌شوند

نمایش آیتم‌ها در رابط کاربری

تا اینجا فقط داده‌ها را دریافت کرده‌ایم.
مرحله بعد این است که این داده‌ها را در لیست HTML نمایش دهیم.

برای این کار، یک متد جدید در UI Controller می‌سازیم به نام populateItemList.


ساخت متد populateItemList

این متد آرایه آیتم‌ها را دریافت می‌کند، روی آن‌ها حلقه می‌زند و برای هر آیتم یک عنصر li می‌سازد.

کد

// UI Controller
const UICtrl = (function () {
  return {
    populateItemList: function (items) {
      let html = '';

      items.forEach(function (item) {
        html += `
          <li class="collection-item" id="item-${item.id}">
            <strong>${item.name}: </strong>
            <em>${item.calories} Calories</em>
            <a href="#" class="secondary-content">
              <i class="edit-item fa fa-pencil"></i>
            </a>
          </li>
        `;
      });

      document.querySelector('#item-list').innerHTML = html;
    }
  };
})();

توضیح ساختار این متد

در این متد چند اتفاق مهم می‌افتد:

1. ساخت متغیر html

ابتدا یک رشته خالی در متغیر html قرار می‌دهیم:

let html = '';

این متغیر قرار است خروجی نهایی HTML را نگه دارد.

2. پیمایش آیتم‌ها با forEach

سپس با forEach روی آرایه items حلقه می‌زنیم:

items.forEach(function (item) {
  // ...
});

3. استفاده از Template String

برای ساخت HTML هر آیتم، از Template String استفاده می‌کنیم تا بتوانیم مقادیر داینامیک را داخل رشته قرار دهیم:

html += `
  <li class="collection-item" id="item-${item.id}">
    <strong>${item.name}: </strong>
    <em>${item.calories} Calories</em>
    <a href="#" class="secondary-content">
      <i class="edit-item fa fa-pencil"></i>
    </a>
  </li>
`;

در اینجا:

  • item.id برای ساخت شناسه یکتا استفاده می‌شود
  • item.name نام آیتم را نمایش می‌دهد
  • item.calories تعداد کالری را نشان می‌دهد

4. درج HTML داخل لیست

در پایان، خروجی نهایی داخل عنصر #item-list قرار می‌گیرد:

document.querySelector('#item-list').innerHTML = html;

فراخوانی populateItemList از داخل App Controller

حالا باید بعد از گرفتن آیتم‌ها از Item Controller، آن‌ها را به UI Controller بفرستیم تا در رابط کاربری نمایش داده شوند.

کد

// App Controller
const App = (function (ItemCtrl, UICtrl) {
  return {
    init: function () {
      // دریافت آیتم‌ها از ساختار داده
      const items = ItemCtrl.getItems();

      // نمایش آیتم‌ها در رابط کاربری
      UICtrl.populateItemList(items);
    }
  };
})(ItemCtrl, UICtrl);

App.init();

توضیح

الان جریان کار به این صورت است:

  1. برنامه با App.init() شروع می‌شود
  2. آیتم‌ها از Item Controller دریافت می‌شوند
  3. همان آیتم‌ها به UI Controller ارسال می‌شوند
  4. UI Controller آن‌ها را به عناصر li تبدیل می‌کند
  5. لیست در صفحه نمایش داده می‌شود

ایجاد آبجکت UISelectors

در این مرحله، ما شناسه #item-list را مستقیم داخل querySelector نوشته‌ایم.
اما اگر بعداً این شناسه تغییر کند، باید در چند جای مختلف کد آن را اصلاح کنیم.

برای حل این مشکل، بهتر است تمام سلکتورهای رابط کاربری را داخل یک آبجکت نگه داریم.

کد

// UI Controller
const UICtrl = (function () {
  const UISelectors = {
    itemList: '#item-list'
  };

  return {
    populateItemList: function (items) {
      let html = '';

      items.forEach(function (item) {
        html += `
          <li class="collection-item" id="item-${item.id}">
            <strong>${item.name}: </strong>
            <em>${item.calories} Calories</em>
            <a href="#" class="secondary-content">
              <i class="edit-item fa fa-pencil"></i>
            </a>
          </li>
        `;
      });

      document.querySelector(UISelectors.itemList).innerHTML = html;
    }
  };
})();

مزیت استفاده از UISelectors

استفاده از آبجکت UISelectors چند مزیت مهم دارد:

  • مدیریت سلکتورها ساده‌تر می‌شود
  • در صورت تغییر کلاس یا id، فقط یک نقطه از کد نیاز به ویرایش دارد
  • کد خواناتر و مقیاس‌پذیرتر می‌شود
  • احتمال خطا در پروژه‌های بزرگ کمتر می‌شود

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


نسخه کامل کد این بخش

در پایان این مرحله، کد ما به شکل زیر خواهد بود:

// Storage Controller

// Item Controller
const ItemCtrl = (function () {
  const Item = function (id, name, calories) {
    this.id = id;
    this.name = name;
    this.calories = calories;
  };

  const data = {
    items: [
      { id: 0, name: 'Steak Dinner', calories: 1200 },
      { id: 1, name: 'Cookie', calories: 400 },
      { id: 2, name: 'Eggs', calories: 300 }
    ],
    currentItem: null,
    totalCalories: 0
  };

  return {
    getItems: function () {
      return data.items;
    }
  };
})();

// UI Controller
const UICtrl = (function () {
  const UISelectors = {
    itemList: '#item-list'
  };

  return {
    populateItemList: function (items) {
      let html = '';

      items.forEach(function (item) {
        html += `
          <li class="collection-item" id="item-${item.id}">
            <strong>${item.name}: </strong>
            <em>${item.calories} Calories</em>
            <a href="#" class="secondary-content">
              <i class="edit-item fa fa-pencil"></i>
            </a>
          </li>
        `;
      });

      document.querySelector(UISelectors.itemList).innerHTML = html;
    }
  };
})();

// App Controller
const App = (function (ItemCtrl, UICtrl) {
  return {
    init: function () {
      // دریافت آیتم‌ها از ساختار داده
      const items = ItemCtrl.getItems();

      // نمایش آیتم‌ها در رابط کاربری
      UICtrl.populateItemList(items);
    }
  };
})(ItemCtrl, UICtrl);

App.init();

جمع‌بندی

در این بخش، داده‌های اولیه برنامه را از Item Controller دریافت کردیم و آن‌ها را با کمک UI Controller در رابط کاربری نمایش دادیم.

در این مرحله:

  • متد getItems را ساختیم
  • آیتم‌ها را در زمان اجرای برنامه دریافت کردیم
  • متد populateItemList را برای ساخت لیست نوشتیم
  • از Template String برای تولید HTML استفاده کردیم
  • سلکتورها را داخل آبجکت UISelectors متمرکز کردیم

در بخش بعدی، سراغ افزودن آیتم جدید به لیست می‌رویم و امکان ثبت وعده غذایی همراه با کالری آن را پیاده‌سازی می‌کنیم.

// 0 comments
#JavaScript#Module Pattern#Item Controller#UI Controller#App Controller#Template String#DOM Manipulation#Calorie Tracker#آموزش جاوااسکریپت#پروژه جاوااسکریپت

نظرات (0)

نظر خود را بنویسید