HM-37. Документирование классов RouteService, RoutePagesContainer. До… (#15)

This commit is contained in:
Nikolay
2020-07-16 09:27:57 +03:00
committed by GitHub
parent e1bc9e6dcd
commit 8ef0e49948
4 changed files with 115 additions and 4 deletions

View File

@ -13,11 +13,24 @@ navMenuButtons.render(NAV_MENU);
const routerPagesContainer = new RouterPagesContainer();
// Новые страницы обязательно добавляем тут
/**
* Добавление страниц в Роутинг выполняется на странице app.js
* @example
* routerPagesContainer.addRoutes([
* {url: '/', pageComponent: MainPage},
* {url: '/api', pageComponent: ApiPage},
* ]);
*/
routerPagesContainer.addRoutes([
{url: '/', pageComponent: MainPage},
{url: '/api', pageComponent: ApiPage},
]);
// Этот метод генерит событие Route, чтобы все компоненты получили его после инициализации
/**
* Этот метод генерит событие Route, чтобы все компоненты получили его после инициализации.
* Поэтому вызывать его надо в самом конце, когда уже созданы все компоненты приложения.
* @example
* // Вызывать его можно только один раз в программе
* routeService.init();
*/
routeService.init();

View File

@ -4,28 +4,62 @@ import NotFoundPage from '../not-found-page';
import './RouterPagesContainer.css';
/**
* @interface Route
* @property {string} url - маршрут страницы начинается с "/"
* @property {Component} pageComponent - компонент (класс) страницы
*/
/**
* Класс для рендера страниц при изменении роутинга
*/
class RouterPagesContainer extends Component {
/**
* Список всех маршрутов
* @type {Route[]}
*/
routes = [];
/**
* Текущая открытая страница
* @type {Component}
*/
currentPage;
/**
* Текущий открытый url
* @type {string}
*/
url;
constructor () {
super('#page-container', document.body);
routeService.onChange(({url}) => {
// Если под указанный url нет pageComponent, то будет испольщована страница NotFound
const {pageComponent: PageComponent = NotFoundPage} = this.routes.find((route) => {
return route.url === url;
}) || {};
// Удаляет предыдущую страницу
if (this.currentPage) {
this.currentPage.destroy();
}
this.currentPage = new PageComponent('#page', this.mainNode);
// Рендерит новую страницу, если url изменился
if (url !== this.currentUrl) {
this.currentUrl = url;
this.currentPage = new PageComponent('#page', this.mainNode);
}
});
}
/**
* Добавляет страницы в компонент, чтобы рендерить их при изменении маршрута. Рекомендуется
* все страницы передавать в app.js в одном месте
* @param {Route[]} routes - список маршрутов с компонентами
*/
addRoutes = (routes) => {
this.routes = this.routes.concat(routes);
}

View File

@ -16,6 +16,11 @@ class EmitService {
* Метод подписки на события компонента
* @param {string} eventName - событие компонента, на которое будет реагировать обработчик
* @param {Function} listener - обработчик события
* @example
* // Подписка на событие
* _.subscribe('click', () => {
* ...
* });
*/
subscribe = (eventName, listener) => {
const listeners = this._events[eventName] || [];
@ -29,6 +34,10 @@ class EmitService {
* Метод генерирует событие
* @param {string} eventName - событие, которое необходимо сгенерировать
* @param {unknown[]} args - аругемнты, который необходимо передать обработчикам события
* @example
* // Сгенерировать событие. Можно передать любое количество аругментов, все эти аргументы в таком же
* // порядке будут переданы подписчикам компонента
* _.next('click', arg1, arg2, ..., argN);
*/
next = (eventName, ...args) => {
const listeners = this._events[eventName];

View File

@ -1,9 +1,28 @@
import EmitService from './EmitService';
import {parse, stringify} from 'querystring';
/**
* @function RouterListener
* @param {string} url - путь роута
* @param {Object<string, string>} query - объект ключ-значение из url
*/
/**
* Константа для события изменения роута
* @private
*/
const ROUTE_CHANGE = 'routeChange';
/**
* Класс для работы с роутингом. Позволяет переходить по роутам и генерит событие изменения роута.
*/
class RouteService extends EmitService {
/**
* @type {boolean} - проверяет чтобы инициализация была не больше одного раза
* @private
*/
_isInit = false;
constructor () {
super();
@ -11,6 +30,10 @@ class RouteService extends EmitService {
this._events[ROUTE_CHANGE] = [];
}
/**
* Метод получения данных url'а
* @private
*/
getUrlData = () => {
return {
url: location.pathname,
@ -18,14 +41,37 @@ class RouteService extends EmitService {
};
}
/**
* Генерирует событие изменения роута
* @private
*/
generateNext = () => {
this.next(ROUTE_CHANGE, this.getUrlData());
}
/**
* Метод инициализации сервиса, чтобы сгенерить первое событие перехода для приложения
*/
init = () => {
this.generateNext();
if (!this._isInit) {
this.generateNext();
return;
}
throw new Error('RouteService можно инициализировать только 1 раз!');
}
/**
* Метод перехода по маршрутам
* @param {string} url - принимает маршрут для перехода
* @param {query} query - объект с парами ключ-значение для url
* @example
* // Переход по заданному url
* _.goTo('/users', {
* key: 'testApi',
* author: 'Petrov',
* });
* // Это создаст строку в url - site.ru/users?key=testApi&author=Petrov
*/
goTo = (url, query) => {
const stringQuery = stringify(query);
const urlWithQuery = url + (stringQuery ? `?${stringQuery}` : '');
@ -33,6 +79,15 @@ class RouteService extends EmitService {
this.generateNext();
}
/**
* С помощью этого метода подписываемся на событие изменения роута.
* @param {RouterListener} listener - слушатель для события изменения роута
* @example
* // Подписка на изменение url
* _.onChange(({url, query}) => {
* ...
* });
*/
onChange = (listener) => {
this.subscribe(ROUTE_CHANGE, listener);
}