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();
توضیح
الان جریان کار به این صورت است:
- برنامه با
App.init()شروع میشود - آیتمها از
Item Controllerدریافت میشوند - همان آیتمها به
UI Controllerارسال میشوند UI Controllerآنها را به عناصرliتبدیل میکند- لیست در صفحه نمایش داده میشود
ایجاد آبجکت 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متمرکز کردیم
در بخش بعدی، سراغ افزودن آیتم جدید به لیست میرویم و امکان ثبت وعده غذایی همراه با کالری آن را پیادهسازی میکنیم.