@akb2/layouts-generator
v1.11.1
Published
`Layouts Generator` - это мини-фреймворк для генерации простых HTML страниц.
Downloads
1,942
Readme
Layouts Generator
Layouts Generator - это мини-фреймворк для генерации простых HTML страниц.
Ключевые оссобенности
- Инкапсуляция стилей
- Компонентный подход
- Легковесность
- Хуки жизненного цикла страниц и компонентов
- Гибкость сборки
Установка и входная точка
Вход *.page.ts (пример src/pages/home/home.page.ts):
import { Page, OnInit, OnViewInit } from "@akb2/layouts-generator/core";
@Page({
templateSrc: "./home.page.pug",
styleSrc: "./home.page.scss"
})
export class HomePage implements OnInit, OnViewInit {
constructor() {
// Вызывается при формировании DOM
}
onInit(): void {
// Логика и подписки
// Безопасно вызывается после DOMContentLoaded
}
onViewInit(): void {
// Доступены корневой элемент @RootElement и @Child
// После window.load
}
}Компоненты страниц @Page
- Декоратор: @Page({ templateSrc, styleSrc?, imports?, isLayout? });
templateSrcФайлы шаблонов:.page.pug;styleSrcФайлы стилей:.page.scss;isLayoutОтметка, что страница содержит структуру HTML документа;importsПеречисление классов компонентов, используемых в шаблоне;- Жизненный цикл:
constructor→onInit()→onViewInit();
onInit() вешается на DOMContentLoaded (или микро-задачу, если документ уже загружен).
onViewInit() вызывается после window.load, внутри доступны ссылки на DOM элементы с помощью @RootElement и @Child.
isLayout - В цепочке зависимостей может быть только страница со значением TRUE или только один компонент.
Компоненты @Component и свойства @Define
import { Component, Define, OnInit } from "@akb2/layouts-generator/core";
@Component({
selector: "app-card",
templateSrc: "./card.component.pug",
styleSrc: "./card.component.scss"
})
export class CardComponent implements OnInit {
// значение по умолчанию — это инициализатор поля
@Define() title = "Заголовок по умолчанию";
@Define() dense = false;
onInit(): void {
// Инициализация компонента
}
}Для передачи данных в компонент для присвоения @Define свойствам используйте объектный синтаксис @{ ... }, помечая объект символом @.
Использование в разметке (на странице/в другом компоненте):
div
- dense = true
app-card@{ title: "Профиль", dense }Примечание по @Define: помечает публичные поля класса как входные параметры компонента. Значение по умолчанию задаётся обычным инициализатором поля (см. title = "...").
Статичные свойства @Static
Внутри компонентов и страниц вы можете использовать декоратор @Static, чтобы использовать эти переменные и значения при генерации проекта. Эти свойства не могут быть изменены в рантайме, они используются только при генерации. Ключевое отличие данного декоратора от @Define в том, что @Static не является входящим параметром и не может переопределяться через пропсы.
Обычные свойства класса
Если создать свойства без какого либо декоратора, тогда эти свойства можно будет изменять в рантайме в рамках хуков жизненного цикла. Нельзя использовать такие свойства в качестве значений атрибутов, только в виде видимого текста.
Общие свойства @Expose
Это особый хук, позволяет объединить в себе все свойства @Static и обычных свойств класса. Это позволяет задать отображаемое значение при компиляции, а так же обновлять его в дальнейшем динамически в рамках хуков жизненного цикла. Так же здесь применимы все те же ограничения, что и в указанных свойствах.
Ссылка на DOM узел экземпляра компонента @RootElement
После запуска приложения на клиенте в поле класса, помеченное декоратором @RootElement фреймворк подставит DOM узел, соответствующий текущему экземпляру компонента. Для страницы или компонента с isLayout: true - ссылка на html тег страницы, для остальных ссылка на собственный DOM элемент. Значение в переменной появляется в момент вызова хука onViewInit и доступен только внутри него.
Связывание DOM элементов с контроллером @Child
Если у вас появляется необходимость в ссылке на конкретный DOM элемент внутри вашего компонента или страницы, то эту задачу решает декоратор @Child. Единственный аргумент декоратора - это строка-идентификатор DOM елемента. Идентификатор может состоять из цифр, букв, тире и подчеркивания, первый символ обязательно должен быть буквой. В шаблоне для указания идентификатора элементу воспользуйтесь специальным синтаксисом *id. По аналогии с @RootElement ссылка присваивается на хуке onViewInit.
import { Component, Child, Define, OnInit, OnViewInit } from "@akb2/layouts-generator/core";
@Component({
selector: "app-title",
templateSrc: "./title.component.pug",
styleSrc: "./title.component.scss"
})
export class TitleComponent implements OnInit, OnViewInit {
@Child("root_elm")
rootElement: HTMLDivElement | undefined;
@Child("id-element")
subTitleElement: HTMLSpanElement | undefined;
@Define()
title = "My title";
@Define()
subTitle = "My sub title";
constructor() {
console.log(this.rootElement); // undefined
console.log(this.subTitleElement); // undefined
}
onInit(): void {
console.log(this.rootElement); // undefined
console.log(this.subTitleElement); // undefined
}
onViewInit(): void {
console.log(this.rootElement); // <div>...</div>
console.log(this.subTitleElement); // <span>My sub title</span>
}
}//- title.component.pug
*root_elm
= title
span*id-element= subTitleСтруктура HTML документа. Поле isLayout
Декораторы @Page и @Component имеют необязательное поле isLayout. Необходимо указать его либо на странице, либо в одном из дочерних компонентов. В цепочке зависимостей @Page -> @Component's -> ... -> @Component может быть только одна сущность с isLayout со значением TRUE.
Этим полем вы указываете фреймворку, кто отвечает за отрисовку базового HTML документа: сама страница или специальный компонент.
Если за отрисовку документа отвечает компонент, то ему доступны все свойства компонента:
- Пропсы
@Define - Проекция контента
- Хуки жизненного цикла
Единственное отличие, что такой компонент не будет иметь в документе своего тега, а декоратор @RootElement устанавливает document в назначенное свойство.
Проекция контента
В компонент по мимо пропсов можно передать шаблон через проекцию контента. Когда разрабатываете шаблон компонента укажите специальный тег g-content, а при вызове компонента в другом шаблоне просто укажите ему содержимое. Это содержимое отрисуется внутри компонента.
Пример:
//- children.component.pug
h1 Some title
div
.children-div Children content
g-content//- parent.page.pug или parent.component.pug
#app
app-children
.parent-div Parent content<div id="app">
<app-children>
<h1>Some title</h1>
<div>
<div class="children-div">Children content</div>
<div class="parent-div">Parent content</div>
</div>
<app-children>
</div>Инкапсуляция
Компоненты имеют инкапсуляцию стилей, поэтому стили одного компонента никак не повлияют на прочие стили.
В SCSS стилях можете использовать обычный SCSS подход, все что привносит фреймворк - это селектор :host. Вы можете писать стили и без него, они прекрасно применятся только к этому компоненту. Данный селектор вам понадобится, если захотите стилизовать саму обертку компонента, тег, указанный в selector свойстве декоратора @Component.
Хуки жизненного цикла
constructor- Cоздание экземпляра;onBeforeStaticAttach()- Перед привязкой данных в PUG шаблонonDefine()- После присвоения значений в@DefineсвойстваonInit()- После готовности DOM (безопасно для подписок/инициализации);onViewInit()- После полной загрузки окна, с корневым элементом;
Не забудьте заимплементить класс компонента или страницы соответствующим интерфейсом хука, ниже список соответствия:
OnBeforeStaticAttach-onBeforeStaticAttach()OnDefine-onDefine()OnInit-onInit()OnViewInit-onViewInit()
Структура компонентов
src/
components/
card/
card.component.ts // Класс + @Component
card.component.pug // Шаблон
card.component.scss // Стили
pages/
home/
home.page.ts // Класс + @Page
home.page.pug // Шаблон
home.page.scss // СтилиФреймворк следит за **/*.ts и указанных в декораторе путях в папках pages и components.
Конфигурация Vite через gBuilder
Создайте vite.config.ts:
import { defineConfig } from "vite";
import { gBuilder } from "@akb2/layouts-generator/builder";
export default defineConfig(
gBuilder({
// Путь к компонентам страниц
pagesPath: "./src/pages",
// Путь к компонентам
componentsPath: "./src/components",
// Путь к выходной папке
distSrc: ".dist",
// Корень проекта
root: ".",
// Путь для открытия браузера в DEV режиме
open: "/.dist/page-home/index.html",
// Минификация FALSE или "terser"
minify: false,
// Каталог для отслеживания изменений
watchDir: "./src",
})
);Что делает gBuilder:
- Автоматически собирает точки входа: runtime, все *.page.ts и *.component.ts (имена формата
page-\<name\>,component-\<name\>); - Настраивает build (outDir, rollupOptions.input и т.д.) и dev-server (порт
1984, строгий порт, watch с polling). - Подключает внутренние плагины: обработка
@Page,@Component,@Define, рантайм, сервер и доп. вотчеры.
Настройки сборки
Фреймворк поддерживает гибкую систему сборки за счёт билдеров для контроллеров, стилей и шаблонов. Ниже представлен список билдеров с сылками на их документацию:
Сборщики стилей
- PageStylesBuilder - отдельный файл стилей для каждой страницы;
- GeneralStylesBuilder - единый файл стилей для всего проекта;
- NoFilesStylesBuilder - без файлов стилей;
Сборщики шаблонов
- SimpleTemplatesBuilder - обычная сборка HTML файлов;
- AttributesStylesTemplatesBuilder - сборка стилей в атрибуты;
Краткий чек-лист
- Определите страницу через
@Page({ templateSrc, styleSrc? }); - Создавайте переиспользуемые блоки через
@Component({ selector, templateSrc, styleSrc? }); - Отмечайте входные параметры как
@Defineи задавайте дефолты инициализаторами полей; - Используйте хуки
onInit,onViewInitпри необходимости; - Настройте
vite.config.tsчерезgBuilder(...);
