tysonfury2015, надеюсь, когда нибудь ты отойдешь от той "хрени", которую ты употребляешь, ибо такую ересь можно "нести" только в нетрезвом состоянии.
По делу: tsigel, попробовал учесть все ваши замечания, кроме методов в 3-4 строки =). Ну и немного изменил хранилище данных (точнее его наполнение), ибо столкнулся с проблемой его переполнения. class Tysonfury2015_idi_mimo{ /** * @constructor * @param {Object} config{url: 'path/to/json', perPage: Integer, output: { container: 'element class/id'}} */ constructor(config){ this.config = config; this.init(); this.storageToken = 'Data__' + Math.round(new Date().getTime() / 1000); } /** * Получет данные в формате JSON по адресу this.config.url * * @param {Callback} */ getData(success){ fetch(this.config.url) .then((response)=>{ if (response.status !== 200){ console.error('Response error! Status - '+response.status); return; } response.json().then((response)=>{ success(response); }); }) .catch((error)=>{ console.error(error); }); } /** * Рабиваем массив с данными по страницам * * @param {Array} */ splitDataByPages(data){ let pages = [], header = data.shift(), numPages = Math.ceil(data.length / this.config.perPage); for (let i = 0; i < numPages; i++){ pages[i] = []; for(let j = 0; j < this.config.perPage; j++){ if (data.length === 0) break; pages[i].push(data.shift()); } } this.putDataToStorage({header, pages}); } /** * Добавляет данные в sessionStorage * * @param data */ putDataToStorage(data){ sessionStorage.setItem(this.storageToken, JSON.stringify(data)); } /** * Возвращает данные из sessionStorage * * @return data */ getDataFromStorage(){ return JSON.parse(sessionStorage.getItem(this.storageToken)); } /** * Удаляет все данные из sessionStorage , которые относятся к этому классу */ clearStorage(){ Object.keys(sessionStorage) .filter((key)=>{ return /^Data__\d+$/.test(key); }) .forEach((key)=>{ sessionStorage.removeItem(key); }); } /** * Генерирует основную структуру таблицы * Таблица (table), заголовок(thead) */ makeTable(){ let table = document.createElement('table'), thead = document.createElement('thead'), tr = document.createElement('tr'), header = this.getDataFromStorage().header; for (let item of header){ let td = document.createElement('td'); td.innerHTML = item.title; tr.appendChild(td); } thead.appendChild(tr); table.appendChild(thead); this.table = table; } /** * Генерирует таблицу (tbody) по странице num * * @param {Number} num - текущая страница */ setPage(num = 1){ num = num < 1 || typeof num !== 'number' ? 1 : num >= this.getDataFromStorage().pages.length ? this.getDataFromStorage().pages.length : num; let page = this.getDataFromStorage().pages[num - 1], tbody = document.querySelector(this.config.output.container+' table tbody'); if (!tbody){ tbody = document.createElement('tbody'); } else { tbody.innerHTML = ''; } page.forEach((row)=>{ let tr = document.createElement('tr'); row.forEach((cell)=>{ let td = document.createElement('td'); td.innerHTML = cell; tr.appendChild(td); }); tbody.appendChild(tr); }); this.table.appendChild(tbody); } /** * Генерирует структуру постраничной навигации */ makePagination(){ let numPages = this.getDataFromStorage().pages.length; if (numPages <= 1) return; let items = document.createElement('ul'); for (let i = 0; i < numPages; i++){ let item = document.createElement('li'); item.innerHTML = i+1; items.appendChild(item); } items.firstChild.classList.add('active'); this.pagination = items; } /** * Устанавливает слушателей событий */ setListeners(){ if (this.pagination){ this.pagination.addEventListener('click', (e)=>{ if (e.target.tagName !== 'LI' || e.target.classList.contains('active')) return false; document.querySelector(this.config.output.container+' ul .active').classList.remove('active'); e.target.classList.add('active'); this.setPage(+e.target.innerHTML); }); } } /** * Последовательно вызывает методоы необходимые для генерации, обработки таблицы и навигации по ней */ init(){ this.clearStorage(); this.getData((data)=>{ this.splitDataByPages(data); this.makeTable(); this.setPage(1); this.makePagination(); let container = document.querySelector(this.config.output.container); container.appendChild(this.table); if (this.pagination){ container.appendChild(this.pagination); } this.setListeners(); }); } } Если я Вас правильно понял и улучшил код, то, если не сложно, подскажите, что еще можно исправить/улучшить? |
Lemme,
Судя по коду вы не используете ide (по крайней мере при reformatCode не осталось бы выравненных присвоений). Это не плохо но с ide удонее. Мне нравится этот гайд по стилю кода. Стало лучше. Мне не ясно зачем тут localStorage? потому как если данные тянутся с сервера то их должно быть не много. И они должны тянуться постронично. На сколько я понимаю это просто для себя. Ок. clearStorage - удалить ключи можно в 1 проход. getData - зачем колбек если у вас есть промис? Возвращайте промис, красиво же! Вы много используете красивых итераторов, но по данным бежите обчсным фором. Почему? В коде должно быть единообразие по максимому. Допустимы сильные отличия в пользу производительности там где она нужна. по возможности действия метода должны нести описательный характер, например в setPage вы проверяете валидность индекса, но намного лучше это вынести в отдельный метод это в 10 раз повысит читабельность метода Я на практике убедился что много однострочных методов - это хорошо, и условия тоже хорошо бывыносить. Это позволяет не вникать в скобки и прочее, а сразу понять суть проверки по названию метода. |
Lemme, тебя не смущает, что твоя таблица (Table) работает со страницами?
splitByPages switchPage pagination :) Это из серии car.cookBorsch(); rabbit.fly(); window.swim() |
Цитата:
Цитата:
Цитата:
for (let key in sessionStorage){ if (/^Data__\d+$/.test(key)){ sessionStorage.removeItem(key); } } Цитата:
Цитата:
по возможности действия метода должны нести описательный характер, например в setPage вы проверяете валидность индекса, но намного лучше это вынести в отдельный метод это в 10 раз повысит читабельность метода Я на практике убедился что много однострочных методов - это хорошо, и условия тоже хорошо бывыносить. Это позволяет не вникать в скобки и прочее, а сразу понять суть проверки по названию метода. Возьму на заметку, спасибо. |
Цитата:
|
Цитата:
Цитата:
var reg = /^Data__\d+$/; Object.keys(sessionStorage).forEach((key) => { if (reg.test(key)) { sessionStorage.removeItem(key); } }); Вынесение объявления рег выражения позволит не создавать его при итерации каждого имени. Методы не просто по возможности должны носить описательный характер. Всякому дроблению должен быть конец :) Не знаю правильно или нет, но мне очень нравится разделять методы которые должны выполнять логику от тех что несут реализацию. И по возможности их не мешать. Ну на примере того же setPage (мне нравится typescript пример будет на нем) public setPage(index:number):void { if (this.hasPage(index)) { this.changeCurrentPage(index); this.render(); } } public render():void { this.clear(); this.createBody(); } private changeCurrentPage(index:number):void { this.currentPage = index; } Конечно многие скажут что удалять тело таблицы и потом его создавать - накладная операция, а таблица должна быть быстра, так что тут это не совсем удачный пример, НО метод clear - нужная штука, он может быть переиспользован в удалении таблице или изменении данных от сервера и прочее, и отдельный метод на создание данных тоже нужен. дробление методов позволяет увеличить переиспользуемость написанного кода. |
Lemme,
Оптимизации и красивости кода должны гармонировать, не стоит писать лишний проход по массиву если его можно не писать и код будет красив, но при этом если массив заведомо мал, а метод используется редко и за один проход выглядит не красиво - не надо пытаться свалить все в 1 кучу (ну то есть не надо пытаться отфильтровать и отмапить и отсортировать в 1 проход массив из 5 элементов, профита вы не увидите). |
tsigel, спасибо за помощь=)
|
Lemme,
Перебирая объекты не забывайте про hasOwnProperty Цитата:
getData() { var promise = fetch(this.config.url); promise.catch(...); returm promise.then(...); } init() { this.getData().then((data) => { ... }); } |
Цитата:
|
Часовой пояс GMT +3, время: 21:56. |