HtmlixRouter

В Htmlix можно использовать роутер для обновления истории, а также смены отображаемых компонентов в зависимости от переданного url.

Роутер создается в экжемпляре приложения, в поле .router, для этого нужно использовать функцию HtmlixRouter(StateMap, routes) которя возвращает экземпляр HtmlixState с новым полем .router. Первый параметр StateMap - объект описания приложения, routes - объект с картой роутов, ключами которого являются маршруты с которыми в будущем будет сравниваться url при изменении адреса.

Как работает router? Перед инициализацией приложения и созданием всех компонентов, роутер "смотрит" url броузера, и сравнивает его с ключами из параметра routes затем найдя соответствие, добавляет все компоненты которых нет в поле 'first' (за исключением виртуальных массивов) в объект fetchComponents (см. выше #fetchComponents), таким образом он перестраивает описание приложения в зависимости от текущего url, те компоненты (за исключением виртуальных массивов) для которых шаблоны отдаются на данном url, мы указываем в поле first - они создадутся сразу после загрузки страницы, а те компоненты для которых нет шаблонов на данном адресе, будут добавлены автоматически в объект fetchComponents - роутером, они создадутся сразу после дозагрузки шаблонов из файла templatePath: "/static/templates/index.html".(Для синхронного создания компонентов можно использовать templateVar см. ниже # Загрузка шаблонов из .js файла - templateVar).

Затем уже в ходе работы приложения мы используем функцию роутера this.rootLink.router.setRout(url) в которой мы меняем url, роутер сравнит новый url с ключами из параметра routes и найдя совпадение поменяет все компоненты из поля routComponent, на те которые должны быть на данном url. В Html разметке, теги где будут меняться отображение компонентов отмечаются data-router_carts=router, data-router_main="router" и т.д.

Например:

var routes = {

    ["/"]: {

        first: ["categories", 'carts', "menu", "home_page"], 
        /// компоненты которые есть в html файле указываются в этом массиве, остальные будут загружены с шаблона, в fetch запросе асинхронно

        routComponent: {

            router_carts: "carts",   //компоненты соответствующие данному роуту
            router_main: "home_page"

        },

        templatePath: "/static/templates/index.html" // папка для загрузки шаблонов
    },  

    ["/cart/:idCart"]: { //знак : в начале слова - говорит что это параметр и сравенение не требуется, проверяет только его наличие на данной позиции

        first: ["categories", 'cart_single', "menu", "home_page"], 
        routComponent: {
            router_carts: "cart_single",
            router_main: "home_page",

        },
        templatePath: "/static/templates/index.html"
    },

    ["/category/:idCategory"]: { 

        first: ["categories", 'carts', "menu", "home_page"], 
        routComponent: {

            router_carts: "carts",
            router_main: "home_page"

        }, 
        templatePath: "/static/templates/index.html" 
    },  

        ["/create/category"]: {

        first: ["menu", "create_category"], 
        routComponent:{ 

            router_main: "create_category"
        }, 
        templatePath: "/static/templates/index.html" 
    },  

            ["/create/cart/"]: {

        first: ["menu", "create_cart"], 
        routComponent:{ 

            router_main: "create_cart"
        }, 
        templatePath: "/static/templates/index.html" 
    },


}

Выше приведен фрагмент кода из прототип SPA интернет магазина

В нем каждый ключ это один из возможных url для данного приложения. Знак : в начале слова говорит что эта часть url - является параметром и с ней сравнения не требуется, требуется только ее присутствие на данной позиции. Также есть знак * в конце слова, говорит только сравнивать все что до звездочки, далее игнорируется например если у нас есть несколько похожих адресов /category1/json/, /category2/json/ и т.д. мы указываем в ключе /category*/json/ и создаем один объект для описания роута, чтобы не дублировать код. Знак * после слеша /* говорит не учитывать все что после слеша, то есть если роут будет ["/category/:categId/"] то он может совпать только с /category/cat_name/, но не /category/cat_name/other/, а если поставить звездочку после слеша то совпадет, так как будет проверяться только наличие, но не количество

Далее:

  • first - имена компонентов, которые есть в html разметке на данном адресе сервера, чтобы взять из них шаблоны. Используется при первой загрузке приложения.
  • routComponen- объект с названиями элементов в которых переключаются компоненты на данном url, например:
        routComponent: { //используется в методе `.setRout(historyUrl)` 

            router_carts: "carts",  //найдет div элемент в котором есть data-router_carts="router" и на данном historyUrl вставит в него компонент carts
            router_main: "home_page" // аналогично, найдет data-router_main="router" и заменит все что в нем есть на "home_page"

        }, 

Таким образом вызвав из любой точки this.rootLink.router.setRout(historyUrl) - мы не только изменим историю в броузере но и поменяем компоненты отображаемые на данном url в объекте routComponent, метод сравнит переданный historyUrl с картой ключей объекта routes и найдя совпадение поменяет отображаемые компоненты в соответствующих элементах страници. Если не найдет совпадение выдаст в консоли ошибку что не можен найти url.

  • templatePath - путь к файлу с шаблонами для компонентов, шаблонов которых нет на данном адресе url. Используется при первой загрузке приложения.