Документация на русском
Github репозиторий Всем привет! В этой статье я расскажу, как пользоваться Matreshka.js на трех несложных примерах. Мы рассмотрим базовые возможности фреймворка, познакомимся с тем, как работать с данными и разберем коллекции. Пост является краткой компиляцией переводов из этого репозитория. Для начала стоит ознакомиться с приложением Hello World, которое вынесено из поста на сайт. При обновлении свойства x произойдет три вещи: При вводе текста в текстовое поле: Как видите, не нужно вручную отлавливать событие ввода в поле текста; при изменении значения свойства не нужно вручную устанавливать значения HTML узлам; не нужно объявлять дескриптор самостоятельно.  Демо Следующий пример — реализация формы авторизации на сайте. У нас есть два текстовых поля: логин и пароль. Есть два чекбокса: «показать пароль» и «запомнить меня». Есть одна кнопка: «войти», которая активна только тогда, когда форма валидна. Скажем, что валидация формы пройдена если длина логина не меньше 4 символов, а длина пароля не меньше 5 символов. Немного теории: Matreshka.Object играет роль класса, создающего объекты типа ключ-значение. В каждом экземпляре класса можно отделить свойства, отвечающие за данные (то что будет передано не сервер, например) от других свойств (то, что серверу не нужно, но определяет поведение приложения). В данном случае, логин, пароль и “запомнить меня” являются данными, которые мы отправляем на сервер, а свойство, говорящее о том, валидна ли форма — нет. Подробная и актуальная информация об этом классе находится в документации. Итак, создадим класс, который наследуется от Matreshka.Object. Так как “приложение” очень небольшое, всю логику можно разместить в конструкторе класса.  Перво-наперво, объявим данные по умолчанию. Метод setData не только устанавливает значения, но и объявляет свойства, отвечающие за данные. Т. е. userName, password и rememberMe должны быть переданы на сервер (в этом примере просто выведем JSON на экран). Так как при разработке приложений, рекомендуется ипользовать всю мощь ECMAScript 2015, и, так как конструктор Matreshka.Object вызвает setData с переданным в него аргументом, мы инициализируем дефольные данные с помощью единственного вызова super (который сделал бы то же семое, что и Matreshka.Object.call(this, { ... })) для того, чтоб код стал симпатичнее. Код ниже делает то же самое, что и предыдущий: Объявляем свойство, isValid, которое зависит от свойств userName и password. При изменении любого из этих свойств (из кода, консоли или с помощью привязанного элемента), свойство isValid тоже изменится. isValid будет равно true, если длина имени пользователя не меньше четырех, а длина пароля — не меньше пяти. Метод calc — это еще одна крутая возможность фреймворка. Одни свойства могут зависеть от других, другие от третьих, в третьи вообще от свойств другого объекта. При этом, вы защищены от цикличных ссылок. Метод прекращает работу если встречается с опасными зависимостями. Теперь, связываем свойства объекта и элементы на странице. Первым делом объявляем песочницу. Песочница нужна для того, чтоб ограничить влияние экземпляра одним элементом на странице и избежать конфликтов (например, если на странице есть два элемента с одним и тем же классом). Затем привязываем остальные элементы.  Как видите, для остальных элементов используется нестандартный селектор :sandbox, ссылающийся на песочницу (на элемент с классом .login-form). В данном случае это не обязательно, так как страница содержит только нашу форму. В ином случае, если на странице есть несколько форм или других виджетов, настоятельно рекомендуется ограничивать выбираемые элементы песочницей. Затем, связываем кнопку, отвечающую за отправку формы, и свойство isValid. Когда isValid равно true, добавляем элементу класс "disabled", когда false — убираем. Это пример одностороннего связывания, а точнее, значение свойства объекта влияет на состояние HTML элемента, но не наоборот. Вместо такой записи можно использовать более краткую: См. документацию к объекту binders. Связываем поле с паролем и свойство showPassword (“показать пароль”) и меняем тип инпута в зависимости от значения свойства (:bound(KEY) — это последний нестендартный селектор). getValue: null означает то, что мы переопределяем стандартное поведение фреймворка при привязке элементов формы. Добавляем событие отправки формы. submit — обычное, произвольное DOM или jQuery событие, sandbox — наша форма (.login-form). Такое событие и ключ должны быть разделены двоеточием. Это синтаксический сахар DOM событий, т. е. событие можно навешать любым другим способом, в том числе, и используя addEventListener: В обработчике вызываем метод login, который объявим ниже, и предотвращаем перезагрузку страницы, отменяя стандартное поведение браузера используя preventDefault. Последний штрих — метод login. Для примера, метод выводит на экран результирующий объект, если форма валидна. В реальном приложении, содержимым функции, очевидно, должен быть ajax запрос на сервер. В самом конце создаём экземпляр класса. Можете снова открыть консоль и изменить свойства вручную: Демо С данными вида ключ-значения разобрались. Рассмотрим коллекции. Скажем, задача звучит так: вывести список неких людей в виде таблицы.  Чтобы не усложнять пример, поместим заранее подготовленные данные в переменную data. (имена и телефоны получены с помощью генератора случайных данных)  Для начала, как обычно, создаём HTML разметку. Объявим коллекцию Users, которая наследуется от Matreshka.Array. Укажем свойство itemRenderer, которое отвечает за то как элементы массива будут рендериться на странице. В данном случае, указан селектор в качестве значения, ссылающийся на шаблон в HTML коде.  Свойство itemRenderer может принимать и другие значения, в том числе, функцию или HTML строку. И укажем значение свойства Model, определяя класс элементов, содержащихся в коллекции. Класс User мы создадим немного позже, для начала определим конструктор новосозданного класса коллекции. При создании экземпляра класса Отлично. Но мы собираемся использовать как можно больше возможностей ECMAScript 2015, улучшающих код. Поэтому, мы будем использовать вызов super для заполнения массива. Теперь объявляем “Модель”: класс User, который наследуется от уже знакомого нам Matreshka.Object. Устанавливаем данные, переданные в конструктор методом setData, или, как обычно, вызываем super. Затем, дожидаемся события render, которое срабатывает тогда, когда соответствующий HTML элемент был создан, но еще не вставлен на страницу. В обработчике привязываем соответствующие свойства соответствующим HTML элементам. Когда значение свойства изменится, innerHTML заданного элемента тоже поменяется. Есть возможность заменить прослушиваение события "render" созданием специального метода onRender (см. доку), но, чтоб не усложнять этот пример, оставим так. В конце создадим экземпляр класса Users, передав данные в качестве аргумента Всё. При обновлении страницы вы увидите таблицу со списком юзеров. Демо Теперь откройте консоль и напишите: Как видите, в таблицу добавился новый элемент. А теперь вызовите  Или любой другой метод массива (sort, splice, pop...). Matreshka.Array, кроме собственных методов, содержит все без исключения методы стандартного JavaScript массива. Затем, Как как видно из примеров, не нужно вручную следить за изменениями в коллекции, фреймворк самостоятельно ловит изменения данных и меняет DOM. Не забывайте, что Matreshka.Array поддерживает собственный набор событий. Вы можете отлавливать любое изменение в коллекции: добавление, удаление, пересортировку элементов методом on. (выведет в консоль имя добавленного пользователя) Как говорится в документации к itemRenderer можно определять рендерер на уровне класса Model. Это ответ на частозадаваемый вопрос: почему я должен определять рендерер на уровне коллекции. Вместо определения itemRenderer для класса Users можно определить свойство renderer для класса User. На самом деле, есть несколько способов имплементации такого приложения. Не нужно определять Model если объекты, входящие в массив не имеют никакой серьезной логики. Приложение, описанное выше можно реализовать, используя один единственный класс. Так же, можно использовать парсер байндингов, который по умолчанию используется классом Matreshka.Array, определив рендерер прямо в классе и не добавляя ничего в HTML. Спасибо всем тем, кто сообщал об опечатках на сайте. Всем добра! Веб разработчик