Инновации в полнофункциональных средах JavaScript для рендеринга на стороне сервера продолжаются быстрыми темпами. Marko разработан под эгидой eBay, который использует его на своем сайте электронной коммерции. Marko задуман как простой в освоении и высокопроизводительный фреймворк.
Райан Карниато, создатель SolidJS, принимал участие в разработке Marko. Он описывает его как «созданный специально для удовлетворения высоких требований к производительности платформы eBay». Учитывая, что eBay ежемесячно привлекает 307 миллионов пользователей, Марко почти наверняка справится с вашим вариантом использования.
Компоненты Марко
Давайте начнем исследование Марко с его системы компонентов. У Марко есть одна из самых простых систем определения и обнаружения компонентов, когда-либо созданных. Здесь вы можете увидеть простое определение компонента — палитру цветов. Обратите внимание, что в основном файле index.marko есть элемент HTML с именем <color-picker>
, а также свойство, содержащее массив шестнадцатеричных цветов. Как Марко находит color-picker
компонент?
Ответ заключается в том, что Марко начинает с каталога, в котором обнаружено использование компонента, а затем, начиная с родственных каталогов, движется вверх в поисках каталога /comComponent, содержащего требуемое определение компонента. Если в коде приложения такой компонент не найден, Марко обратится к установленным зависимостям и также просканирует их.
Обратите внимание, что Марко ищет вверх, чтобы каталоги в отдельных ветках не знали друг о друге. Это обеспечивает своего рода область видимости компонентов.
В нашем случае Марко не придется далеко ходить, потому что есть файл /comComponents/color-picker/index.marko. (Марко также будет загружать компоненты из файла с именем компонента в каталоге компонентов или файла внутри каталога компонента с именем компонента в виде папки и файла.)
Если вы посмотрите файл /comComponents/color-picker/index.marko, вы увидите определение компонента выбора цвета, показанное в листинге 1.
Листинг 1. color-picker.marko
import getDefaultColors from '../../util/getDefaultColors.js'
class {
onInput(input) {
var colors = input.colors || getDefaultColors();
this.state = {
selectedColor: colors[0],
colors
};
}
handleColorSelected(color) {
this.state.selectedColor = color;
}
}
<div>
<color-picker-header color=state.selectedColor/>
<color-picker-footer colors=state.colors on-color-selected("handleColorSelected")/>
</div>
Листинг 1 содержит основные элементы компонента. Он начинается с импорта другого файла JS с помощью оператора импорта (простая функция JavaScript, которая будет использоваться, если цвета не передаются). Далее он определяет необходимые структуры JavaScript; в данном случае это класс и функция. Последним является фактическая разметка шаблона, которая в основном включает в себя два других компонента: верхний и нижний колонтитул.
Давайте подробнее рассмотрим определение этого класса. Он определяет два метода.
Ввод свойства
Первый метод onInput()
. Это метод жизненного цикла, который получает входной аргумент и позволяет изменять состояние компонента (подробнее о состоянии ниже).
Обратите внимание на входную переменную. Это зарезервированный идентификатор в Marko, который разрешается в свойства, переданные от родительского элемента выше. Помните, что основной компонент содержит свойство элемента. colors
это указывало на жестко запрограммированный список шестнадцатеричных цветов. Теперь доступ к ним осуществляется дочерним компонентом через input.colors
свойство. Свойства полностью реактивны, то есть система обеспечит обновление всего, что зависит от реквизитов.
Обработка событий
Второй метод класса: handleColorSelected
, который является пользовательским обработчиком событий. Вы можете увидеть используемый обработчик в листинге 1, где расположен нижний колонтитул:
<color-picker-footer colors=state.colors on-color-selected("handleColorSelected")/>
Перевод: Когда on-color-selected
событие сработало, вызовите handleColorSelected
метод, передавая любые имеющиеся аргументы.
Штат в Марко
Состояние в Marko похоже на React в том смысле, что оно должно быть неизменным, а это означает, что необходимо назначить новое состояние для обновления одного свойства. Марко предоставляет способ принудительного запуска обновления состояния:
this.setStateDirty(property);
Как и в других реактивных средах, состояние в Marko моделирует внутреннее состояние компонента. Реактивная система отвечает за обновление пользовательского интерфейса и других значений, зависящих от этого состояния.
Итерация и вызов событий в Marko
Теперь давайте посмотрим, как компонент нижнего колонтитула делает две вещи: перебирает цветовые реквизиты и запускает их. on-color-selected
событие.
Код color-picker-footer/index.marko показан в листинге 2.
Листинг 2. color-picker-footer
<div.color-picker-footer>
<div.color-picker-selection-container>
<for|color| of=input.colors>
<div>
<color-picker-selection
color=color
on-color-selected("handleColorSelected", color)/>
</div>
</for>
<input key="hexInput" placeholder="Hex value" on-input("handleHexInput")/>
</div>
</div>
Вы можете видеть, что итерационная работа выполняется с помощью <for>
ярлык. <for>
тег может указать свою переменную-итератор с именем внутри |
символы. В этом случае итератору присваивается имя color
. Коллекция, по которой необходимо выполнить итерацию, идентифицируется с помощью of
имущество, в данном случае имеется в виду input.colors
перешло от родителя.
Каждый член input.colors
переменная будет выведена как div с доступом к color
переменная. По синтаксису он похож на другие фреймворки, такие как React.
Генерация событий в Марко
Большую часть работы по выбору цвета с помощью щелчка мыши выполняет color-picker-selection
компонент, который выводится внутри for
итератор вместе с color
свойство и обработчик для on-color-selected
.
В листинге 3 показано color-picker-selection
компонент.
Листинг 3. Компонент выбора цвета
class {
handleColorSelected() {
this.emit("color-selected");
}
}
style {
.color-picker-selection {
width: 25px;
height: 25px;
border-radius: 5px 5px 5px 5px;
display: flex;
flex-direction: column;
margin: 5px 0px 0px 5px;
float: left;
}
}
<div.color-picker-selection
on-click("handleColorSelected")
on-touchstart("handleColorSelected")
style={
backgroundColor: input.color
}/>
Большинство color-picker-selection
посвящен определению макета (т. е. маленьких цветных квадратов, позволяющих выбирать цвет). Здесь вы видите CSS как часть структуры компонента в блоке стилей, который определяет небольшой закругленный квадрат. Обратите внимание, что вы также можете определить CSS в отдельном файле .css с именем style.css. Вы можете увидеть этот последний подход в каталоге /color-picker-selection.
В разметке шаблона обратите внимание на встроенный стиль, который используется для установки цвета фона в шестнадцатеричный цвет, заданный для input.color
.
Также обратите внимание на то, как on-click
и on-touchstart
события используются для фиксации взаимодействия пользователя с цветным квадратом. Мероприятие передается handleColorSelected
, который определен в заголовке файла. Оно использует this.emit("color-selected")
выстрелить custom color-selected
событие.
Напомним, что color-picker-footer
часы для индивидуальных мероприятий с on-color-selected("handleColorSelected", color)
. Обратите внимание, что обработчик вызывает handleColorSelected
и прохождение color
переменная. Но где определена эта функция?
Гибкость определения компонентов
Ответ: он определен в отдельном файле компонент.js в том же каталоге, подобно отдельному файлу style.css, который вы видели ранее. Возможность поместить отдельные части компонента в один файл или в отдельные файлы (или в комбинацию того и другого) обеспечивает хорошую гибкость в определении компонентов по мере их роста от простого к сложному.
Ожидайте тега в Марко
Марко также включает в себя <await>
тег для обработки асинхронного рендеринга. <await>
позволяет вам передать обещание, а фреймворк будет ждать его результата и отображать его только тогда, когда он станет доступен. (Это аналог одноименного компонента в Svelte.)
<await>
тег упрощает работу с асинхронным выводом.
Простая и неожиданная структура
Марко оправдывает свое обещание быть простым в обучении. Во-первых, он содержит лишь небольшое количество основных тегов, которые необходимо изучить. С другой стороны, эти теги довольно просты и работают в соответствии с принципом наименьшего неожиданности. Marko — это полнофункциональная платформа, поэтому вы также получаете готовый рендеринг на стороне сервера с интеграцией для таких серверов, как Express.
В сочетании с интуитивно понятной системой определения компонентов, сборщиками для Webpack и Rollup и высочайшей производительностью Marko дает веские основания считать, что он станет вашим следующим фреймворком JavaScript.