<output class="out"></output>
<input class="in" type="text">
<script src="seemple.min.js"></script>
<script>
const app = new Seemple();
app.bindNode('x', '.in, .out');
app.x = 'Рілі сімпл фреймворк для створення односторінкових веб додатків';
</script>
Вступ
Фічі
- Реактивний API, що дозволяє ефективно вирішувати складні й заплутані задачі
- Менше помилок у коді
- Можливість рефакторінга легасі додатків, без переписування з нуля
- Освоїти фреймворк можна за кілька годин завдяки відсутності складних концепцій
- Одна з найзручніших документацій серед JavaScript бібліотек
Для кого цей фреймворк?
Seemple.js заповнює прірву між джуном та сеньором
- Для новачків у веб програмуванні, бажаючих освоїти розробку односторінкових додатків
- Для full-stack розробників, для яких front-end розробка стоїть на другому місці після back-end
- Для всіх тих, кого не влаштовує поточний порядок речей у всесвіті веб розробки
Яку бізнес-задачу вирішує фреймворк?
Не секрет, що поріг входження в веб розробку стає все вище, вимог до сучасного розробника все більше, кількість залежностей в проектах може доходити до декількох сотень. Незважаючи на те, що вивчати JavaScript стало модним, попит на розробників, які можуть виконати поставлене завдання все сильніше перевищує пропозицію.
Завдяки простоті фреймворка, навіть початківці веб розробки можуть швидко почати робити маленькі, потім середні, а потім і великі веб додатки. Це означає, що веб студії отримують можливість економити гроші, наймаючи молодших спеціалістів, які, в свою чергу, не могли знайти роботу раніше.
Тільки лише для новачків?
Дві речі, які видають Seemple.js, як простий фреймворк - це пряме звернення до DOM при оголошенні двостороннього зв'язування даних і відсутність будь-яких вимог до архітектури і шаблонів проектування. В іншому Seemple.js - сучасний фреймворк загального призначення для необмежених в розмірі односторінкових веб додатків, розроблений з використанням технологій сьогоднішнього дня. А факт того, що фреймворк використовує, можливо, весь потенціал акцесорів в JavaScript, як мінімум, може викликати непідробний інтерес.
Як користуватися документацією
Рівні важливості
Документація розбита на три рівні важливості.
Перший рівень - найважливіше
Вивчивши найважливіші властивості і методи, ви можете сміливо приступати до роботи. З класами, методами і властивостями, поміченими значком необхідно розібратися в першу чергу.
Другий рівень - рекомендується вивчити
Після того, як ви освоїли необхідні для швидкого старту можливості, можете ознайомитися з іншими, менш важливими (але все ще важливими) властивостями і методами фреймворку.
Третій рівень - інші методи і властивості
Для того, щоб не лякати новачків речами, які використовуються відносно рідко, інші методи і властивості за замовчуванням приховані. Якщо ви хочете знати про фреймворк все, без винятку, клікніть на "Розширений режим" зліва, в меню.
Увага, якщо ви перейдете по посиланню до методу або властивості третього рівня важливості, то режим документації автоматично переключиться в "Розширений режим".
Помилки в документації
У кінці кожної статті документації є посилання на код цієї статті. Виправити помилку можна прямо в редакторі на Github. Якщо з яких-небудь причин не можете відправити виправлення або ви знайшли помилку там де немає такого лінку, виділіть необхідний текст з помилкою і натисніть CTRL+Enter. З'явиться вікно, що дозволяє відправити повідомлення розробнику.
Документація розроблена з використанням JSDoc3 і GitHub Flavored Markdown.
Модулі
Якщо ви використовуєте CommonJS, адреси окремих модулів вказані в кожній статті цієї документації. Розмір результуючого JavaScript файлу можна скоротити за рахунок імпорту тільки необхідних частин фреймворка.
// кожну статичну властивість будь-якого об'єкта
// або функції можна імпортувати в вигляді модуля
const SeempleArray = require('seemple/array');
const propBinder = require('seemple/binders/prop');
const bindNode = require('seemple/bindnode');
Імпорт головного модуля підтягне весь фреймворк. Як правило, це не потрібно.
const Seemple = require('seemple');
Модуль класу Seemple, без
binders
,Array
иObject
знаходиться за адресою'seemple/seemple'
Приклади
Hello World
Написати перший додаток за допомогою фреймворка Seemple.js дуже просто.
1. Створіть HTML файл з наступним змістом
<!DOCTYPE html>
<html>
<head>
<title>Мій перший додаток на базі Seemple.js</title>
</head>
<body>
<input type="text" class="my-input">
<div class="my-output"></div>
<script
src="https://finom.github.io/seemple/seemple.min.js">
</script>
<script src="js/app.js"></script>
</body>
</html>
2. Створіть клас у файлі js/app.js
// присвоюємо html байндер змінній з коротким ім'ям
const htmlBinder = Seemple.binders.html;
// створюємо клас, який успадковується від Seemple
class Application extends Seemple {
constructor() {
super();
// пов'язуємо властивість x і текстове поле
this.bindNode('x', '.my-input');
// пов'язуємо властивість x і блок з класом my-output
this.bindNode('x', '.my-output', htmlBinder());
// слухаємо зміни властивості x
this.on('change:x', () =>
console.log(`x змінений на "${this.x}"`));
}
}
const app = new Application();
3. Це все!
Тепер можете відкрити консоль розробника (клавіша F12) і написати:
app.x = 'Hello World!';
Посилання
Інші приклади
1. TodoMVC - список справ. (Код з анотаціями)
2. TreeView - деревовидний список необмеженої вкладеності.
3. Markdown editor - найпростіший редактор Markdown.
4. Simple SoundCloud player - пошук музики, що використовує SoundCloud API.
5. Contact List - дозволяє додавати, видаляти, сортувати, змінювати і шукати контакти.
Клас Seemple
Шлях до модуля CommonJS: 'seemple/seemple'
Клас Seemple
- це ядро фреймворка Seemple.js, від якого успадковуються Seemple.Array, Seemple.Object і кожен клас створюваного додатка. Він містить основний функціонал фреймворка: медіатори, залежності, прив'язки до DOM, механізм подій тощо.
Як правило, цей клас, (як і Seemple.Array і Seemple.Object), не використовуються безпосередньо. Замість цього, від нього успадковуються класи, створювані розробником.
Посилання
Приклади
Створення екземпляру
const seemple = new Seemple();
Спадкування
class MyClass extends Seemple {
constructor() {
this.sayHello();
}
sayHello() {
alert("Hello World!");
}
}
Спадкування за допомогою функції Seemple.Class
const MyClass = Seemple.Class({
'extends': Seemple,
constructor() {
this.sayHello();
},
sayHello() {
alert("Hello World!");
}
});
Seemple#bindNode(key, node, binder, eventOptions)
→
object
Пов'язує властивість об'єкта з HTML елементом
bindNode
- це єдиний метод класу Seemple, який відповідає за зміни DOM. Він створює міст між значенням властивості і станом HTML елемента на сторінці: від простого інпут до складного віджета (складність елементів не обмежена). Після зв'язування властивості екземпляра і HTML елемента не потрібно більше стежити за синхронізацією даних та виду.
Зверніть увагу, що у метода є статичний аналог, який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсовуючи інші аргументи вправо.
const bindNode = require('seemple/bindnode');
const object = {};
bindNode(object, key, node, binder, eventOptions);
// замість this.bindNode(key, node, binder, eventOptions);
Для двостороннього зв'язування елемента і значення властивості, в метод передаються три аргументи: ім'я властивості, HTML елемент і правило прив'язки (байндер, біндер, binder, прівязчік). Байндер, в свою чергу, є звичайним об'єктом і може мати наступні властивості: on
, getValue
, setValue
, initialize
, destroy
(докладніше див. binder). Всі п'ять властивостей опційні. Це дозволяє також оголошувати і односторонні прив'язки.
Метод
bindNode
підтримує прив'язки "багато до багатьох". З одною властивістю можна зв'язати кілька елементів, а з одним елементом можна зв'язати кілька властивостей, в тому числі і від різних екземплярів різних класів.
this.bindNode('myKey', '.my-element', {
on: 'click',
getValue () {...},
setValue () {...}
});
Наприклад, ви хочете зв'язати властивість об'єкта з елементом input[type="checkbox"]
:
this.bindNode('myKey', '.my-checkbox', {
// Коли змінюється стан елемента?
// - За подією 'click'
on: 'click',
// Як витягти стан елемента?
// - Повернути значення 'checked'
getValue() {
return this.checked;
},
// Як встановити стан елемента?
// - Встановити значення 'checked'
setValue(v) {
this.checked = !! v;
}
});
Після оголошення прив'язки можна встановлювати значення властивості об'єкта самим звичним способом, а елемент змінить свій стан автоматично. При кліці на чекбокс, значення властивості теж зміниться на відповідне.
// Встановлює checked = true
this.myKey = true;
Більш складний приклад: зв'язування властивості об'єкта з віджетом jQuery UI
<div class="my-slider"></div>
this.bindNode('myKey', '.my-slider', {
// Коли змінювати стан елемента?
// - За подією 'slide'
on: 'slide',
// Як витягти стан елемента?
// - Повернути значення віджета 'value'
getValue() {
return $(this).slider('option', 'value');
},
// Як встановити стан елемента?
// - Встановити значення 'value'
setValue(v) {
$(this).slider('option', 'value', v);
},
// Як ініціалізувати віджет?
// Зробити це можна будь-яким способом,
// але initialize надає трохи синтаксичного цукру
initialize() {
$(this).slider({ min: 0, max: 100 });
}
});
// Встановить значення слайдера 42
this.myKey = 42;
Виглядає просто, але у вас, швидше за все, винекне питанням: "Як зробити так, щоб мені не довелося кожен раз прописувати ці правила?". Дійсно, на сторінці може бути дуже багато однотипних елементів: текстових полів, полів з специфікації HTML5, можуть бути і сторонні віджети (про що говорить приклад вище).
Як видно з документації до аргументів методу bindNode
, третій аргумент не обов'язковий. Цю проблему вирішує масив Seemple.defaultBinders, який містить функції, що перевіряють HTML елемент на відповідність заданим правилам і повертають відповідний Байндер або undefined
. З'являється можливість багаторазово скоротити код, виносячи правила прив'язки в окрему частину вашого коду, а для прив'язки використовувати синтаксис без третього аргументу:
this.bindNode('myKey', '.my-element');
Як це зробити? Потрібно додати функцію, яка перевіряє ваш елемент на відповідність деяким правилам в початок масиву Seemple.defaultBinders.
const checkboxBinder = () => {
return {
on: 'click',
getValue () {
return this.checked;
},
setValue (v) {
this.checked = !! v;
}
}
};
// Метод unshift додає функцію
// у початок масиву Seemple.defaultBinders
Seemple.defaultBinders.unshift(node => {
// Перевіряємо, чи це чекбокс
if (node.tagName === 'INPUT' && node.type === 'checkbox') {
// Якщо перевірка пройдена, повертаємо новий байндер
return checkboxBinder();
}
});
this.bindNode('myKey', '.my-checkbox');
this.myKey = true;
Що робити, якщо вам потрібно передати аргументи для ініціалізації якогось плагіна або віджету? Можна вручну викликати функцію, яка повертає Байндер.
const uiSlider = (min, max) => {
return {
on: 'slide',
getValue() {
return $(this).slider('option', 'value');
},
setValue(v) {
$(this).slider('option', 'value', v);
},
initialize() {
$(this).slider({ min: min, max: max });
}
}
};
this.bindNode('myKey1', '.my-slider1', uiSlider(0, 100));
this.bindNode('myKey2', '.my-slider2', uiSlider(1, 1000));
this.myKey1 = 42;
this.myKey2 = 999;
Для глобального доступу до байндера, можна розширити Seemple.binders.
Seemple.binders.uiSlider = uiSlider;
// ...
this.bindNode('myKey1', '.my-slider1', Seemple.binders.uiSlider(0, 100));
this.bindNode('myKey2', '.my-slider2', Seemple.binders.uiSlider(1 1000));
Seemple.defaultBinders з коробки містить підтримку всіх без винятку HTML елементів форм: select
(включаючи multiple
), textarea
, output
, input
(в тому числі і всі типи із специфікації HTML5: text
, checkbox
, radio
, range
, number
, date
, search
, time
, datetime
, datetime-local
, color
та інших). Це означає, що для стандартних елементів вказувати Байндер не обов'язково.
<input type="color" class="my-color-input">
this.bindNode('myColor', '.my-color-input');
this.myColor = '#66bb6a';
Після прив'язки, вам доступний новий нестандартний CSS селектор :bound(KEY)
.
this.bindNode('myKey', '.my-element');
// Знайде елемент .my-inner-element який є в '.my-element'
this.bindNode('myAnotherKey', ':bound(myKey) .my-inner-element');
І розширюється синтаксис можливих імен подій:
this.bindNode('myKey', '.my-element');
// Відловити клік на елементі .my-element
this.on('click::myKey', () => {...});
// Відловити клік на елементі .my-element .my-inner-element
this.on('click::myKey(.my-inner-element)', () => {...});
Якщо елемент не знайдений, кидається виняток
"Bound element is missing"
. Для того, щоб уникнути помилки використовуйте метод Seemple#bindOptionalNode
Створення пісочниці
Seemple#bindNode вміє асоціювати екземпляр класу з "головним" HTML елементом, створюючи так звану пісочницю. Це потрібно для того, щоб обмежити вплив об'єкта одним HTML елементом. Для прив'язки пісочниці використовується спеціальна властивість sandbox
.
<div class="my-sandbox">
<!-- Your HTML code -->
</div>
this.bindNode('sandbox', '.my-sandbox');
Визначення пісочниці додає безліч зручностей програмісту. наприклад:
- Дозволяє використовувати методи Seemple#select і Seemple#$
- Додає можливість використовувати селектор
:sandbox
в методах Seemple#bindNode, Seemple#select, Seemple#$ - Додає синтаксичний цукор для делегованих DOM подій в методі Seemple#on
Слід мати на увазі, що тільки один HTML елемент може бути пов'язаний з властивістю
sandbox
, інакше кидається помилка. Для оголошення пісочниці можна скористатися методом Seemple#bindSandbox. Перед тим, як оголосити байндінг, метод одв'язує попередню пісочницю.
// Оголошуємо пісочницю
this.bindNode('sandbox', '.my-sandbox');
// .my-element шукається в пісочниці
this.bindNode('myKey', ':sandbox .my-element');
// Для делегованих подій всередині пісочниці не потрібно вказувати ключ
this.on('click::(.my-button)', () => {...});
// Виведе в консоль елемент .inner-node,
// Який знаходиться всередині пісочниці
console.log(this.$('.inner-node'));
Важливі особливості роботи методу і спеціальні прапори
Четвертим аргументом eventOptions
в метод bindNode
можна передати об'єкт, що складається з прапорів, описаних нижче, глобальних прапорів (наприклад, silent
), або кастомних даних, які потраплять в оброблювачі подій bind
і bind:KEY
.
this.on('bind:x', evt => {
console.log(evt.foo); // bar
});
this.bindNode('x', node, binder, { foo: 'bar' });
Для ознайомлення з важливими тонкощами роботи bindNode
інформація нижче обов'язкова до ознайомлення. При цьому, імена прапорів запам'ятовувати не обов'язково.
Прапор exactKey=false
Якщо в якості key
передати строку, що містить точку, то така строка буде інтерпрітірована як шлях до властивості у вкладеному об'єкті. Seemple.js буде слухати зміни в усьому дереві, розриваючи зв'язок для старих гілок, і створюючи його для нових.
this.a = { b: { c: 'foo' } };
this.bindNode ('a.b.c', node);
this.a.b.c = 'bar'; // Оновить елемент значенням bar
const oldB = this.a.b;
this.a.b = { c: 'baz' }; // Оновить елемент значенням baz
// Елемент не оновиться, оскільки він більше не пов'язаний з цією гілкою
oldB.c = 'fuu';
У разі, якщо ім'я властивості має бути використано як є, скористайтеся прапором exactKey
зі значенням true
.
this['a.b.c'] = 'foo';
this.bindNode('a.b.c', node, binder, {
exactKey: true
});
this['a.b.c'] = 'bar';
Прапор getValueOnBind
При наявності у байндера getValue
, стан елемента буде вилучено та присвоєно властивості відразу після виклику bindNode
за умови, якщо прив'язувана властивість має значення undefined
. Для того, щоб форсувати цю поведінку навіть якщо властивість - не undefined
використовуйте прапор getValueOnBind
зі значенням true
. Для скасування цієї поведінки, використовуйте той же прапор зі значенням false
.
Прапор setValueOnBind
При наявності у байндері setValue
, значення властивості буде встановлено в якості стану елемента відразу після виклику bindNode
за умови, якщо прив'язувати властивість має значення відмінне від undefined
. Для того, щоб форсувати цю поведінку навіть якщо властивість - undefined
використовуйте прапор setValueOnBind
зі значенням true
. Для скасування цієї поведінки, використовуйте той же прапор зі значенням false
.
Прапори debounceGetValue=true
і debounceSetValue=true
Важливою особливістю методу bindNode
є те, що до зміни властивостей і зміни стану елемента застосовується мікропаттерн debounce. Це означає, що якщо прив'язана властивість буде змінена багаторазово за короткий проміжок часу (наприклад, в циклі), стан елемента буде оновлено лише один раз після затримки в кілька мілісекунд (завдяки debounceSetValue=true
). І навпаки: якщо стан елемента змінюється багато разів за короткий проміжок часу (тобто викликається відповідна DOM подія), властивість отримає нове значення тільки один раз після короткої затримки (завдяки debounceGetValue=true
).
const input = document.querySelector('.my-input');
this.bindNode('x', input);
this.x = 'foo';
console.log(input.value === 'foo'); // false
setTimeout(() => {
console.log(input.value === 'foo'); // true
});
Для скасування цієї поведінки, використовуйте прапори debounceSetValue
i/або debounceGetValue
зі значенням false
.
Прапори debounceSetValueOnBind=false
і debounceGetValueOnBind=false
Як говорилося вище, до зміни властивостей і зміни стану елемента застосовується мікропаттерн debounce. Це не стосується самого моменту зв'язування. При виклику bindNode
стан елемента або значення властивості встановлюється синхронно. debounceSetValueOnBind
і debounceGetValueOnBind
встановлені як true
вмикають debounce і для цих процесів.
Прапори debounceSetValueDelay=0
і debounceGetValueDelay=0
Ці прапори дозволяють вказати затримку debounce. debounceSetValueDelay
задається при використанні debounceSetValue
і debounceSetValueOnBind
, debounceGetValueDelay
- при використанні debounceGetValue
і debounceGetValueOnBind
.
Прапор useExactBinder=false
Навіть якщо в метод bindNode
передати конкретний байндер, фреймворк спробує відшукати байндер у Seemple.defaultBinder і розширити його властивостями переданого об'єкта. Така можливість дозволяє використовувати дефолтний частково перевизначений байндер.
Наприклад, ми хочемо зв'язати input[type="text"]
з властивістю. За замовчуванням, стандартний байндер для цього елемента містить властивість "on"
зі значенням "input"
. Це означає, що значення властивості об'єкта і стан елемента будуть синхронізовані відразу після введення або видалення символу користувачем. У разі, якщо ви хочете, щоб синхронізація відбувалася після DOM події "blur"
, вам буде потрібно передати третім аргументом об'єкт, що містить єдину властивість "on"
. Цей об'єкт об'єднається зі стандартним байндером, зберігши при цьому значення getValue
і setValue
.
this.bindNode('x', '.my-input', { on: "blur" });
Для скасування цієї поведінки і використання байндера як він є, в об'єкт події можна передати прапор useExactBinder
зі значенням true
.
this.bindNode('x', node, binder, {
useExactBinder: true
});
Повертає object - self
Генерує події bind bind:KEY
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string | Ім'я властивості |
node | string node $nodes | HTML елемент, який повинен бути пов'язаний з властивістю об'єкта |
binder optional | binder | Байндер, що містить властивості |
eventOptions optional | eventOptions | Об'єкт події, в який можна передати ключ |
Посилання
Seemple#bindNode(bindings, binder, eventOptions)
→
object
Альтернативний синтаксис Seemple#bindNode: можливість передати об'єкт з байндінгамі
У метод Seemple#bindNode можна передати об'єкт щоб уникнути багаторазового виклику методу і скоротити код. Ключі об'єкта - це імена властивостей, а значення можуть бути наступними:
- HTML елемент
- Об'єкт з властивостями
node
(HTML елемент) іbinder
- Масив об'єктів з властивостями
node
(HTML елемент) іbinder
Якщо binder
переданий другим аргументом, то він служить байндером для тих елементів, для яких байднер не вказано явно.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
bindings | object | (див. приклад) |
binder optional | binder | (див. вище) |
eventOptions optional | eventOptions | (див. вище) |
Приклади
this.bindNode({
foo: '.custom-checkbox',
'bar.length': 'textarea'
});
this.bindNode({
foo: {
node: ':sandbox .aaa',
binder: Seemple.binders.html()
},
bar: '.bbb',
baz: [{
node: '.ccc'
}, {
node: document.querySelector('.ddd'),
binder: Seemple.binders.prop('baz')
}]
}, {
// will be used as a binder for .bbb and .ccc
setValue(value) {
foo(value);
}
});
Seemple#bindNode(batch, commonEventOptions)
→
object
Альтернативний синтаксис, що дозволяє оголосити необмежену кількість байндінгов одним викликом методу.
Варіація методу дозволяє передати масив об'єктів, що містять інформацію про байндінги. Елемент масиву повинен містити наступні властивості:
key
- ім'я властивостіnode
- елемент, для якого оголошуємо зв'язування зkey
binder
- байндер (не обов'язково)event
- об'єкт події (не обов'язково)
Другий аргумент - загальний об'єкт події, що розширює event
для кожного байндінга (властивості з event
є більш пріоритетні).
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
batch | array | Масив байндінгів |
commonEventOptions optional | eventOptions | Загальні для всіх об'єктів властивості події |
Приклади
this.bindNode([{
key: 'a',
node: '.my-node',
binder: {
setValue(v) {
doSomething(v);
}
}
}, {
key: 'b',
node: document.querySelectorAll('.bar')
event: {
foo: 'bar'
}
}, {
key: 'c.d.e',
node: jQuery('.baz'),
binder: Seemple.binders.html(),
event: {
silent: true,
exactKey: true
}
}], {
getValueOnBind: false
});
Seemple#bindOptionalNode()
Працює в точності так само, як і Seemple#bindNode але не кидає виняток, якщо аргумент node
- порожній масив, undefined
або не існує
У метода є статичный аналог.
Посилання
Приклади
this.bindOptionalNode('myKey', '.my-element');
Seemple#bindSandbox(node, eventOptions)
Прив'язує пісочницю
При цьому, "одв'язує" попередню, якщо така існує.
У метода є статичний аналог.
Генерує події bind bind:sandbox
Аргументи
Iм'я | Тип | Опис |
---|---|---|
node | string node $nodes | Елемент, який повинен стати пісочницею |
eventOptions optional | eventOptions | Об'єкт події |
Посилання
Приклади
this.bindSandbox('.my-element');
Seemple#calc(target, source, handler=(v)=>v, eventOptions)
Створює залежність значення однієї властивості від значень інших
Метод calc
створює залежність значення властивості (аргумент target
) від значень інших властивостей (аргумент source
). При зміні source
, target
обчислюється автоматично.
Зверніть увагу, що у метода є статичний аналог, який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо.
const calc = require('seemple/calc');
const object = {};
calc(object, target, source, handler, eventOptions);
// Замість this.calc(target, source, handler, eventOptions);
Аргумент source
має кілька варіацій.
Строка
Властивість target
буде залежати від властивості source
.
this.b = 1;
this.calc('a', 'b', b => b * 2);
console.log(this.a); // 2
Масив строк
Властивість target
буде залежати від властивостей, перерахованих в source
.
this.b = 1;
this.c = 2;
this.d = 3;
this.calc('a', ['b', 'c', 'd'], (b, c, d) => b + c + d);
console.log(this.a); // 6
Об'єкт з властивостями object
і key
В цьому випадку можна оголосити залежність властивості target
від іншого об'єкта.
const someObject = { b: 1 };
this.calc('a', {
object: someObject,
key: 'b'
}, b => b * 2);
console.log(this.a); // 2
Значенням властивості key
можна передати масив ключів.
const someObject = {
b: 1,
c: 2,
d: 3
};
this.calc ('a', {
object: someObject,
key: ['b', 'c', 'd']
}, (b, c, d) => b + c + d);
console.log(this.a); // 6
Масив об'єктів з властивостями object
і key
Так можна оголосити залежність властивості від властивостей різних об'єктів.
const someObjectX = {
b: 1,
c: 2
};
const someObjectY = {
d: 3
};
this.calc('a', [{
object: someObjectX,
key: ['b', 'c']
}, {
object: someObjectY,
key: 'd'
}], (b, c, d) => b + c + d);
console.log(this.a); // 6
Масив, що комбінує строки (власні властивості) і об'єкти
this.b = 1;
this.c = 2;
const someObject = {
d: 3,
e: 4
};
this.calc('a', ['b', 'c', {
object: someObjectX,
key: ['d', 'e']
}], (b, c, d, e) => b + c + d + e);
console.log(this.a); // 10
З міркувань чистоти коду, комбінувати строки і об'єкти в масиві source
не рекомендується. Замість строк краще передати об'єкт, у якого властивість object
має значення цільового об'єкту. Приклад нижче робить те ж саме, що і попередній.
this.b = 1;
this.c = 2;
const someObject = {
d: 3,
e: 4
};
this.calc('a', [{
object: this, // цільовий об'єкт - це this
keys: ['b', 'c']
}, {
object: someObjectX,
key: ['d', 'e']
}], (b, c, d, e) => b + c + d + e);
console.log(this.a); // 10
Точка в імені властивості-джерела
Якщо ім'я ключа містить точку, метод ініціює залежність від властивості у вкладеному об'єкті.
this.b = { c: { d: 1 } };
this.e = { f: { g: 2 } };
this.calc('a', ['b.c.d', 'e.f.g'], (d, g) => d + g);
console.log(this.a); // 3
Те ж саме стосується і зовнішніх об'єктів
this.b = { c: { d: 1 } };
const someObject = { e: { f: { g: 2 } } };
this.calc('a', [{
object: this
key: 'b.c.d'
}, {
object: someObject
key; 'e.f.g'
}], (d, g) => d + g);
console.log(this.a); // 3
Метод захищений від циклічних залежностей (наприклад a залежить від b, b залежить від c, а c залежить від a) і при помилці обчислень не блокує сторінку і не кидає виняток про переповнення стека.
Як ви могли помітити, аргументи функції handler
завжди розташовані в тому ж порядку, що і властивості з source
.
У разі, якщо потрібно змінити значення властивості-джерела і зробити це так, щоб цільова властивість не була обчислена заново, використовуйте метод Seemple#set з прапором skipCalc
рівним true
.
this.calc('a', 'b', handler);
this.set('b', newValue, {
skipCalc: true
});
Важливі особливості роботи методу і спеціальні прапори
Четвертим аргументом в метод calc
можна передати об'єкт події eventOptions
, що містить спеціальні прапори, які описані нижче, прапори для методу set
(наприклад, silent
), або кастомні дані, які передаються в обробники події change:KEY
.
this.on('change:a', evt => {
console.log(evt.foo); // 'bar'
});
this.calc('a', source, handler, { foo: 'bar' });
Прапор debounceCalc=true
При виклику методу calc
цільова властивість обчислюється без затримок, але при зміні властивості-джерела застосовується патерн debounce. Це означає, що цільова властивість зміниться через кілька мілісекунд і тільки один раз, навіть якщо властивості-джерела змінилися багаторазово за короткий проміжок часу.
this.b = 1;
this.c = 2;
this.d = 3;
this.calc('a', ['b', 'c', 'd'], (b, c, d) => b + c + d);
this.on('change:a', () => {
// Обробник буде викликаний один раз незважаючи на те,
// що властивості-джерела змінилися тричі
console.log(`a is changed to ${this.a}`); // a is changed to 60
});
this.b = 10;
this.c = 20;
this.d = 30;
console.log(this.a); // 6 замість 60
Для скасування debounce при зміні властивостей, тобто для включення моментального оновлення цільового властивості (як було в попередніх версіях методу), четвертим аргументом методу calc
можна передати прапор debounceCalc
рівний false
.
this.b = 1;
this.c = 2;
this.d = 3;
this.calc ('a', ['b', 'c', 'd'], (b, c, d) => b + c + d, {
debounceCalc: false
});
this.on('change: a', () => {
// Обробник буде викликаний тричі,
// кожен раз коли властивості b, c чи d змінюються
// a is changed to ... 15, 33, 60
console.log (`a is changed to $ {this.a}`);
});
this.b = 10;
this.c = 20;
this.d = 30;
console.log(this.a); // 60
Прапор debounceCalcOnInit=false
Як говорилося вище, при виклику методу calc
цільова властивість обчислюється відразу, а при зміні властивостей-джерел - ні. Увімкнути debounce і при першому обчисленні властивості можна передавши в якості властивості об'єкта події прапор debounceCalcOnInit=true
.
this.on('change:a', () => {
// Обробник буде викликаний один раз через невеликий проміжок часу
console.log(`a is changed to $ {this.a}`); // a is changed to 6
});
this.b = 1;
this.c = 2;
this.d = 3;
this.calc ('a', ['b', 'c', 'd'], (b, c, d) => b + c + d, {
debounceCalcOnInit: true
});
console.log(this.a); // undefined
На практиці debounceCalcOnInit
навряд чи стане в нагоді. Потрібно лише пам'ятати, що є прапор який включає "повний debounce".
Прапор debounceCalcDelay=0
Прапор дозволяє вказати затримку debounce при використанні debounceCalc
і debounceCalcOnInit
.
Прапор setOnInit=true
Відомо, що при виклику методу calc
властивість відразу отримує нове значення. Для того, щоб скасувати цю поведінку і обчислити властивість target
тільки тоді, коли властивість-джерело вперше змінено, використовуйте прапор setOnInit
рівний false
.
this.calc('a', 'b', b => b * 2, {
setOnInit: false
});
console.log(this.a); // undefined
// Але якщо оновити this.b, для властивості a буде обчислено нове значення
this.b = 1;
Прапор exactKey=false
Як говорилося вище, в якості імені властивості-джерела можна передати строку, що містить точки. Таке ім'я буде витлумачено як шлях до властивості у вкладеному об'єкті. У разі, якщо ім'я має бути використано як є, скористайтеся прапором exactKey
зі значенням true
.
this['foo.bar.baz'] = 1;
this.calc('a', 'foo.bar.baz', fooBarBaz => fooBarBaz * 2, {
exactKey: true
});
console.log(this.a); // 2
Прапор promiseCalc=false
Цей прапор дозволяє використовувати екземпляри Promise
всередині функції, що обчислює значення. Значенням шуканої властивості стає результат успішного виконання промісу.
Увага!
Promise
неможливо скасувати. Використовуйте можливістьpromiseCalc
акуратно та не допускайте багаторазового виклику складних функцій.
this.calc('a', ['b', 'c'], (b, c) => {
return new Promise(resolve => {
setTimeout(() => {
resolve(a + b)
}, 1000);
});
}, {
promiseCalc: true
});
this.b = 1;
this.c = 2;
// "a" буде змінений через секунду
this.calc('response', 'data', async (data) => {
const resp = await fetch(url, {
method: 'post',
body: data
});
return resp.json();
}, {
promiseCalc: true
});
Аргументи
Iм'я | За замовчуванням | Тип | Опис |
---|---|---|---|
target |
| string | Ім'я властивості яка залежить від інших властивостей |
source |
| string array | Від яких властивостей залежить шукана властивість (див. опис вище) |
handler optional | (v)=>v
| function | Функція, що повертає нове значення |
eventOptions optional |
| eventOptions | Об'єкт, в який можна передати якісь дані для обробника події, який слухає зміни |
Приклади
this.calc('greeting', 'name', name => `Hello, ${name}!`);
this.name = 'World';
// ... in a moment
alert(this.greeting); // 'Hello, World!'
Обчислення периметра прямокутника по двох сторонах (і сторін по периметру)
this.a = 3;
this.b = 4;
this
.calc('p', ['a', 'b'], (a, b) => (a + b) * 2)
.calc('a', ['p', 'b'], (p, b) => p / 2 - b)
.calc('b', ['p', 'a'], (p, a) => p / 2 - a);
alert(this.p); // 14
this.on('change: p', () => {
// "периметр змінений і дорівнює 18"
console.log(`периметр змінений і дорівнює ${this.p}`);
});
this.a = 5;
Seemple#calc(batch, commonEventOptions)
Додаткова можливість методу Seemple#calc, що дозволяє оголосити кілька обчислюваних властивостей одним викликом
Перший аргумент - об'єкт, ключі якого - імена властивостей, які потрібно обчислювати, а значення - об'єкти, що містять:
source
- властивості, від яких залежить цільова властивість;handler
- як саме буде обчислена властивість (за замовчуванням дорівнює(value) => value
);event
- об'єкт події (не обов'язково).
Другий аргумент - загальний об'єкт події, що розширює event
для кожної шуканої властивості (властивості з event
мають більший приоритет).
source
може приймати будь-який вид опис вище (рядок, масив рядків, об'єкт з властивостями key
і object
, масив таких об'єктів).
Аргументи
Iм'я | Тип | Опис |
---|---|---|
batch | array | Об'єкт містить інформацію про обчислюваних властивості |
commonEventOptions optional | eventOptions | Загальні властивості для об'єктів події |
Приклади
this.calc({
x: {
source: ['a', 'b'],
handler: (a, b) => a + b
},
y: {
source: {
object: someObject,
key: 'c'
},
event: {
setOnInit: false
}
},
z: {
source: [{
object: this,
key: 'x'
}, {
object: someObject,
key: 'd'
}],
handler: (x, d) => x + d
}
}, {
debounceCalc: false
});
Seemple#instantiate(key, class, updateCallback)
→
object
Створює фіксований екземпляр класу
Зверніть увагу, що у метода є статичний аналог.
Метод створює і фіксує екземпляр класу в якості значення заданогї властивості. При спробі перевизначити властивість, замість самого перевизначення, екземпляр оновлюється. Таким чином досягається цілісність програми, зробленої на базі Seemple.js.
Метод є надбудовою над Seemple#mediate і перевизначає медіатор.
Екземпляр класу створюється під час запуску методу instantiate
. Першим аргументом конструктора класу стає поточне значення властивості. У конструкторі класу необхідно передбачити те, що в нього потрапить або undefined
(якщо властивість не містила до цього ніяких даних), або об'єкт, з яким треба щось зробити (наприклад, розширити екземпляр класу властивостями об'єкта).
На ділі це виглядає просто: ви створюєте звичайний клас, який майже завжди приймає якісь дані, які потрібно обробити (наприклад, використовувати їх в методі Seemple.Object#setData).
При спробі привласнити властивості інше значення, внутрішній механізм методу instantiate
, замість присвоювання, робить наступне:
- Якщо вказана функція
updateCallback
, метод запускає його з двома аргументами: поточним значенням властивості і даними, які код намагається привласнити. - Якщо заданий клас успадкований від Seemple.Object, екземпляр оновлюється новими даними, використовуючи метод Seemple.Object#setData з прапором
replaceData=true
. - Якщо заданий клас успадкований від Seemple.Array, екземпляр оновлюється новими даними, використовуючи метод Seemple.Array#recreate.
- Якщо не вказана функція
updateCallback
і якщо класі не успадкований від Seemple.Object або Seemple.Array, екземпляр розширюється властивостями об'єкта, який код намагається привласнити.
Особливістю методу є відсутність обмежень на джерело класу. Класом може виступати будь-яка функція-конструктор. яка ініціалізується за допомогою оператора
new
, а не тільки спадкоємці Seemple.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string array | Ім'я властивості або масив імен властивостей |
class | function | Клас, чий екземпляр стає значенням властивості |
updateCallback optional | function | Функція, викликається при кожній спробі присвоїти чергові дані властивості, що дозволяє кастомізувати логіку поновлення екземпляра класу новими даними. Функція приймає два аргументи: поточне значення властивості (екземпляр класу) і дані, які намагаються привласнити. |
Приклади
class MyClass {
// ...
}
// ...
this.instantiate('x', MyClass);
// намагаємося привласнити властивості інше значення
this.x = { a: 42 };
// this.x як і раніше екземпляр класу MyClass
alert(this.x instanceof MyClass); // true
alert(this.x.a); // 42
Використання updateCallback
.
this.instantiate('x', MyClass, (instance, data) => {
updateSomeHow(instance, data);
});
Отримання батьківского об'єкту та імені властивості. Крім даних (перший аргумент), в конструктор створюваного класу, передається посилання на об'єкт, що викликав instantiate
та ім'я створеної властивості
class MyClass extends Seemple {
constructor(data, parent, key) {
// parent - це екземпляр MyParentClass,
// який створив властивість
// key - им'я властивості ("х")
}
}
const MyParentClass etends Seemple {
constructor() {
this.instantiate('x', MyClass);
}
}
Нестандартний спосіб використання updateCallback
для ігнорування будь-яких змін властивості
this.instantiate('x', SubClass, () => {});
У разі, якщо ваш клас не підтримує використання оператора new
, замість instantiate
скористайтеся методом Seemple#mediate.
this.mediate('x', (data, currentValue) => {
return currentValue instanceof SomeClass
? Object.assign(currentValue, data)
: SomeLib.initInstance(SomeClass, data);
});
Абстрактний приклад з даними великий вкладеності (для лаконічності використовується синтаксис class instance fields)
// app.js
class App extends Seemple {
constructor(appData) {
this.appData = appData;
this.instantiate('appData', AppData);
}
}
// app-data.js
class AppData extends Seemple.Object {
constructor(data) {
super(data)
.instantiate({
friends: Friends,
settins: Settings
});
}
}
// friend.js
class Friend extends Seemple.Object {
constructor(data) {
super(data);
}
}
// friends.js
class Friends extends Seemple.Array {
get Model() { return Friend; }
trackBy = 'id';
constructor(data) {
super(...data);
}
}
// settings.js
class Settings extends Seemple.Object {
constructor(data) {
super(data)
.instantiate('credentials', Credentials);
}
}
// credentials.js
class Credentials extends Seemple.Object {
constructor(data) {
super(data);
}
}
// app-init.js
var app = new App({
settings: {
name: 'Vasiliy Vasiliev',
credentials: {
email: 'vasia.vasia@gmail.com'
}
},
friends: [{
name: 'Yulia Zuyeva',
id: 1
}, {
name: 'Konstantin Konstantinopolsky',
id: 2
}, {
name: 'nagibator3000',
id: 3
}]
});
// дані можна серіалізувати та передати на сервер
JSON.stringify(app.appData);
// потім просто присвоїти чергові дані властивості appData
// при цьому, структура класів не зміниться
app.appData = {
settings: {
name: 'Petr Petrov',
credentials: {
email: 'petr.petrov@gmail.com'
}
},
friends: [{
name: 'Yulechka Zuyeva',
id: 1
}, {
name: 'Konstantin Konstantinopolsky',
id: 2
}]
};
Seemple#instantiate(keyClassPairs, updateCallback)
→
object
Альтернативный синтаксис методу Seemple#instantiate, який дозволяє приймати об'єкт ключ-клас в якості аргументу
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keyClassPairs | object | Об'єкт з властивостями ключ-клас |
updateCallback optional | function | Функція, яка викликається при кожній спробі присвоїти нові данні властивості. |
Приклади
this.instantiate({
x: Class1,
y: Class2,
z: Class3
}, (instance, data) => {
instance.doSomethingWith(data);
});
Seemple#mediate(key, mediator)
Трансформує значення властивості при його зміні
Цей метод використовується для перетворення значення властивості при його зміні. Наприклад, вам потрібно, щоб значення властивості завжди було або певного типу, або цілим числом, або бути не менше нуля і не більше ста тощо.
Зверніть увагу, що у метода є статичний аналог, який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо.
const mediate = require('seemple/mediate');
const object = {};
mediate(object, key, mediator);
// Замість this.mediate(key, mediator);
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string array | Ім'я властивості або масив імен |
mediator | function | Функція-посередник (медіатор, mediator), яка повертає нове значення. У неї передаються такі аргументи: нове значення, попереднє значення, ім'я властивості, сам об'єкт |
Приклади
this.mediate('x', value => String(value));
this.x = 1;
alert(typeof this.x); // "string"
Масив ключів
this.mediate(['x', 'y'], value => String(value));
Seemple#mediate(keyMediatorPairs)
Альтернативный синтаксис методу Seemple#mediate, приймаючий в якості аргументу об'єкт "ключ-медіатор"
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keyMediatorPairs | object | Об'ект із властивостями ключ-медіатор |
Приклади
this.mediate({
x: String,
y: Number,
z: Boolean
});
this.x = 1;
this.y = 2;
this.z = 3;
alert(typeof this.x); // "string"
alert(typeof this.y); // "number"
alert(typeof this.z); // "boolean"
Seemple#off(names, callback, context)
→
seemple
Видаляє обробник події
Видаляє створений раніше обробник. Всі три аргументи опційні. Ви можете видалити як всі події (не передаючи жодного аргументу), так і окремі (передавши тільки ім'я події, передавши ім'я події і обробник, передавши і ім'я події, і обробник, і контекст)
Повертає seemple - self
Генерує події removeevent removeevent:NAME
Аргументи
Iм'я | Тип | Опис |
---|---|---|
names optional | eventNames | Розділений пробілами список імен подій (наприклад, |
callback optional | eventHandler | Функція-обробник |
context optional | object | Контекст |
Посилання
Приклади
this.off('change:x bind');
Видалення всіх подій
this.off();
Видалення події з певним обробником
const handler = function () {
// ...
}
this.on('change:x', handler);
this.off('change:x', handler);
Видалення події з певним контекстом
const object = {};
this.on('change:x', handler, object);
this.off('change:x', handler, object);
Seemple#on(names, callback, triggerOnInit, context)
→
object
Додає обробник події
Метод Seemple#on додає обробник події для екземпляра класу Seemple
. Повний список можливих подій з описом см. Тут: eventNames.
Зверніть увагу, що у методва є статичний аналог, який працює в точності так само, але приймає будь-який об'єкт в якості першого аргументу, зсуваючи інші аргументи вправо.
const on = require('seemple/on');
const object = {};
on(object, names, callback, triggerOnInit, context);
// Замість this.on(names, callback, triggerOnInit, context);
Повертає object - self
Генерує події addevent addevent:NAME
Аргументи
Iм'я | Тип | Опис |
---|---|---|
names | eventNames | Ім'я події або кілька імен, розділених пробілом (наприклад, |
callback | eventHandler | Функція, яка викликається за подією |
triggerOnInit optional | boolean | Якщо аргумент |
context optional | object | Контекст обробника. Іншими словами, |
Посилання
Приклади
this.on('foo', () => {
alert('Custom Event is fired');
});
this.trigger('foo');
Передача контексту
this.on('foo', function() {
alert(this.a); // 5
}, { a: 5 });
this.trigger('foo', 'Hello world');
Виклик обробника відразу після ініціалізації
// Виводить на екран "bar" моментально і чекає на подію "foo"
this.on('foo', () => {
alert('bar');
}, true);
Seemple#on(evtnameHandlerObject, triggerOnInit, context)
→
object
Альтернативний синтаксис: пари "подія-обробник"
У метод Seemple#on можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
evtnameHandlerObject | object | Об'єкт з подіями |
triggerOnInit optional | boolean | Якщо аргумент |
context optional | object | Контекст обробника |
Приклади
this.on({
'custom': evt => ...,
'click::x': evt => ...,
'change:y': evt => ...,
});
Seemple#onDebounce(names, callback, debounceDelay, triggerOnInit, context)
→
object
Додає обробник події, що викликається лише одного разу за певний проміжок часу
Метод дозволяє додати обробник події на екземпляр класу Seemple, усуваючи "деренчання" обробника. Функція може бути викликана лише один раз за певний проміжок часу. В іншому, метод працює так само, як і Seemple#on.
У метода є статичний аналог.
Повертає object - self
Генерує події addevent addevent:NAME
Аргументи
Iм'я | Тип | Опис |
---|---|---|
names | eventNames | Ім'я події або кілька імен, розділених пробілом (наприклад, |
callback | eventHandler | Функція, яка викликається за подією |
debounceDelay optional | number | Затримка |
triggerOnInit optional | boolean | Якщо аргумент |
context optional | object | Контекст обробника |
Посилання
Приклади
this.onDebounce('change:x', () => {
alert(`x = ${this.x}`); // x = 100
}, 300);
this.x = 1;
for(let i = 0; i < 100; i++) {
this.x++;
}
Seemple#onDebounce(evtnameHandlerObject, debounceDelay, triggerOnInit, context)
→
object
Альтернативний синтаксис: пари "подія-обробник"
У метод Seemple#onDebounce можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
evtnameHandlerObject | object | Об'єкт з обробниками подій |
debounceDelay optional | number | Затримка |
triggerOnInit optional | boolean | Якщо аргумент |
context optional | object | Контекст обробників |
Посилання
Приклади
this.onDebounce({
'custom': evt => { ... },
'click::x': evt => { ... },
'change:y': evt => { ... }
});
Seemple#once(names, callback, context)
→
object
Додає обробник подій, який може бути викликаний один раз
Метод працює так само, як і Seemple#on але переданий обробник може бути викликаний тільки один раз.
Зверніть увагу, що у метода є статичний аналог
Повертає object - self
Генерує події addevent addevent:NAME
Аргументи
Iм'я | Тип | Опис |
---|---|---|
names | eventNames | Ім'я події або кілька імен, розділених пробілом (наприклад, |
callback | eventHandler | Функція, яка викликається за подією |
context optional | object | Контекст обробника |
Посилання
Приклади
this.x = 1;
this.once('change:x', () => {
alert('x is changed');
});
this.x = 2; // виводить 'x is changed'
this.x = 3; // нічого не робить
Seemple#once(evtnameHandlerObject, context)
→
object
Альтернативний синтаксис: пари "подія-обробник"
У метод Seemple#once можна передати об'єкт з парами подія-обробник, щоб уникнути багаторазового виклику методу і скоротити код.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
evtnameHandlerObject | object | Об'єкт з подіями |
context optional | object | Контекст обробників |
Посилання
Приклади
this.once({
'custom': evt => { ... },
'click::x': evt => { ... },
'change:y': evt => { ... }
});
Seemple#parseBindings(node, eventOptions)
→
$nodes
Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки.
Починаючи з версії 1.1, Seemple.js включає в себе простий DOM парсер, що обробляє синтаксичні конструкції, укладені в подвійні фігурні дужки. Метод parseBindings
першим аргументом приймає HTML строку, DOM вузол або селектор, відповідний DOM вузлу.
Так як метод є DOM шаблонізатором (а не строковим HTML шаблонізатором), всі дочірні DOM вузли переданого елемента залишаються в своєму колишньому стані (наприклад, DOM події не затираються).
Підтримуваний синтаксис.
- HTML прив'язка ```html <!-- Створить текстовий вузол на місці {{user.name}} і зв'яже властивість name з об'єкта user з цим вузлом JS: this.user = {name: 'Joe'}
--> Hello, {{user.name}}
2. Прив'язка елементів форм.
```html
<!--
Зв'яже властивість "x" об'єкту з текстовим
полем (двостороння прив'язка)
JS: this.x = 'some value';
-->
<input type="text" value="{{x}}">
<!--
Для прив'язки textarea і select потрібно використовувати атрибут value
-->
<textarea value="{{x}}"></textarea>
<select value="{{x}}">...</select>
<!--
Зв'яже властивість "x" об'єкту з чекбоксом
(двостороння прив'язка)
JS: this.x = true;
-->
<input type="checkbox" checked="{{x}}">
- Прив'язка атрибутів. ```html <!-- Значення атрибута href буде залежати від значень властивостей "category" і "someObject.page" (одностороння прив'язка) JS: this.category = 'seemple'; this.someObject = { page: 42 };
--> A link
```
Якщо фігурні дужки не влаштовують, поміняйте їх на щось інше, використовуючи Seemple.parserBrackets
Навіщо потрібен такий метод?
У разі, якщо ви розробляєте велику форму зі стандартними HTML5 полями, метод допоможе зберегти час на оголошення численних прив'язок. Крім цього, parseBindings
корисний у разі створення дуже простих колекцій, які не потребують реалізації складної моделі.
Повертає $nodes - Колекція DOM вузлів, передана в функцію як аргумент
Аргументи
Iм'я | Тип | Опис |
---|---|---|
node | string node $nodes | HTML строка, селектор, DOM вузол або колекція DOM вузлів HTML |
eventOptions optional | eventOptions | Об'єкт події, який буде переданий у всі внутрішні виклики методу Seemple#bindNode |
Приклади
Парсинг заданого вузла
this.parseBindings(node);
Парсинг вузла по селектору
this.parseBindings('.my-node');
Парсинг HTML строки
const $node = this.parseBindings('<h3>Hello, {{name}}</h3>');
this.name = 'Arthur Philip Dent';
Seemple#remove(key, eventOptions)
→
seemple
Видаляє властивість
Повертає seemple - self
Генерує події delete delete:KEY
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string | Им'я властивості або масив имен властивостей, які треба видалити |
eventOptions optional | eventOptions | Об'ект події |
Приклади
this.remove('myKey');
this.remove(['myKey1', 'myKey2']);
Використання eventOptions
this.remove('myKey', {
silent: true
});
Seemple#select(selector)
→
node
null
Повертає елемент з пісочниці, відповідний селектору
Метод дуже схожий на Seemple#selectAll, але повертає лише один елемент або null
У метода є статичний аналог.
Повертає node null
Аргументи
Iм'я | Тип | Опис |
---|---|---|
selector | string | Селектор |
Приклади
this.bindNode('sandbox', '.app');
this.select('.my-element');
// те ж саме, що і
this.nodes.sandbox.querySelector('.my-element');
// те ж саме, що і
$('.app').find('.my-element')[0];
Seemple#selectAll(selector)
→
$nodes
Синонім: Seemple#$
Повертає єлементі з пісочниці, відповідні селектору
Після створення пісочниці методом Seemple#bindNode, можна отримувати і використовувати елементи, що знаходяться в ній. Крім цього, метод підтримує кастомний селектор :bound(KEY)
.
У метода є статичний аналог.
Повертає $nodes
Аргументи
Iм'я | Тип | Опис |
---|---|---|
selector | string | Cелектор |
Приклади
this.bindNode('sandbox', '.app');
nodes = this.selectAll('.my-element');
// те ж саме, що і
nodes = this.$('.my-element'); // $ - посилання на метод selectAll
// те ж саме, що і
nodes = this.$nodes.sandbox.find('.my-element');
// те ж саме, що і
nodes = $('.app').find('.my-element');
Селектор :bound(KEY)
this.bindNode('myKey', '.my-element');
nodes = this.selectAll(':bound(myKey) .my-another-element');
// те ж саме, що і
nodes = this.$nodes.myKey.find('.my-another-element');
// те ж саме, що і
nodes = $('.my-element').find('.my-another-element');
Seemple#set(key, value, eventOptions)
Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу
Список підтримуваних прапорів:
silent
- не викликати подіїchange
іchange:KEY
silentHTML
- не змінювати стан прив'язаних елементівforce
- викликати подіїchange
іchange:KEY
навіть якщо значення властивості не змінилосяforceHTML
- змінити стан прив'язаного елемента, навіть якщо значення властивості не змінилося. Ця опція потрібна, якщо прив'язаний елемент був відмальований після прив'язки (наприклад, вselect
були додані тегиoption
)skipMediator
- запобігає трансформацію властивості медіатором (див. Seemple#mediate)skipCalc
- запобігає роботу залежностей, створених за допомогою Seemple#calc
У метода є статичний аналог.
Генерує події change change:KEY beforechange beforechange:KEY
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string | Ключ |
value | * | Значення |
eventOptions optional | eventOptions | Об'єкт події |
Приклади
this.on('change: myKey', evt => {
alert(evt.value);
});
// Те ж саме, що і this['myKey'] = 3
// або this.myKey = 3
// виводить на екран 3
this.set('myKey', 3);
Використання eventOptions
this.on('change:myKey', evt => {
alert(evt.value);
});
// alert не спрацює
this.set('myKey', 4, {
silent: true
});
Передача даних в обробник
this.on('change:myKey', evt => {
alert(evt.myCustomFlag);
});
// Виводить на екран 42
this.set('myKey', 4, {
myCustomFlag: 42
});
Seemple#set(keyValuePairs, eventOptions)
Альтернативний синтаксис методу Seemple#set "ключ-значення"
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keyValuePairs | object | Об'єкт, що містить пари ключ-значення |
eventOptions optional | eventOptions | Об'єкт події |
Приклади
this.set({
myKey1: 1,
myKey2: 2
});
Передача eventOptions
в якості второго аргумента
this.set({
myKey: 3
}, {
myFlag: 'foo'
});
Seemple#trigger(names, arg)
→
object
Генерує подію
Після додавання обробників подій за допомогою методу Seemple#on, Seemple#onDebounce або Seemple#once, подія може бути сгенерована вручну за допомогою цього методу.
Зверніть увагу, що у метода є статичний аналог.
Повертає object - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
names optional | eventNames | Ім'я події або кілька імен, розділених пробілом |
arg optional | * | Аргументи, які будуть передані обробникам |
Посилання
Приклади
this.on('foo bar', (a, b, c) => {
alert(a + b + c);
});
this.trigger('bar', 1, 2, 3); // alerts 6
Seemple#unbindNode(key, node, eventOptions)
→
seemple
Розриває зв'язок між властивістю і HTML елементом
Використовуючи цей метод, можна видалити доданий раніше, але вже не потрібний зв'язок між властивістю і елементом.
Повертає seemple - self
Генерує події unbind unbind:KEY
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string null | Ключ або список ключів, розділених пробілами. Якщо замість ключа передати null, будуть видалені всі прив'язки для даного об'єкта. |
node optional | string node $nodes | HTML елемент, з яким властивість більше не хоче мати справи |
eventOptions optional | eventOptions | Об'єкт події, в який можна передати якісь дані для обробника або ключ |
Приклади
this.bindNode('myKey', '.my-element');
// Змінює значення властивості і стан HTML елемента
this.myKey = true;
this.unbindNode('myKey', '.my-element');
// Тепер змінюється лише значення властивості
this.myKey = false;
Seemple#unbindNode(bindings, eventOptions)
→
seemple
Альтернативний синтаксис unbindNode
, що дозволяє передати об'єкт з байндінгамі. Див. Seemple#bindNode(2)
Повертає seemple - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
bindings | object | (див. приклад) |
eventOptions optional | eventOptions | (див. вище) |
Приклади
this.unbindNode({
foo: '.aaa'
bar: {
node: '.bbb'
},
baz: [{
node: '.ccc'
}, {
node: '.ddd'
}]
});
Seemple#unbindNode(batch, eventOptions)
Альтернативний синтаксис, що дозволяє видалити необмежену кількість байндінгів одним викликом методу.
Варіація методу дозволяє передати масссів об'єктів, що містять інформацію про байндінги. Елемент масиву повинен містити наступні властивості:
key
- ім'я властивостіnode
- елемент, для якого був об'явлений байндінг зkey
(не обов'язково)
Ця варіація методу зручна тим, що її синтаксис збігається з однією з варіацій методу Seemple#bindNode, дозволяючи привласнити байндінгі змінної для швидкого видалення.
Аргументи
Iм'я | Тип | Опис |
---|---|---|
batch | array | Массив байндингів |
eventOptions optional | eventOptions | (див. вище) |
Приклади
const temporaryBindings = [{
key: 'a',
node: '.my-node',
binder: {
setValue(v) {
doSomething(v);
}
}
}, {
key: 'b',
node: document.querySelectorAll('.bar')
event: {
foo: 'bar'
}
}, {
key: 'c.d.e',
node: jQuery('.baz'),
binder: Seemple.binders.html(),
event: {
silent: true,
exactKey: true
}
}]
this.bindNode(temporaryBindings);
// більше не потрібні ці прив'язки
this.unbindNode(temporaryBindings);
Seemple#$nodes: $nodes
Об'єкт містить колекції (jQuery, Zepto, інстанси вбудованої мікро-бібліотеки, успадкованої від Array.prototype
) прив'язаних елементів для швидкого доступу.
Посилання
Приклади
this.bindNode('myKey', '.my-node');
this.$nodes.myKey; // Те ж саме, що і $('.my-node')
Seemple#isSeemple: boolean
isSeemple
завжди дорівнює true
для экземплярів Seemple
Приклади
alert(object.isSeemple);
Seemple#nodes: node
Об'єкт містить прив'язані елементи для швидкого доступу, у вигляді окремих DOM вузлів.
Зверніть увагу, кожна властивість об'єкта містить перший вузол з пов'язаних з соотвутствующий властивістю. Для отримання всіх вузлів, пов'язаних з певною властивістю, використовуйте Seemple#$nodes.
Посилання
Приклади
this.bindNode('myKey', '.my-node');
this.nodes.myKey; // Те ж саме, що і $('.my-node')[0]
Seemple.Class(prototype, statics)
→
class
Шлях до модуля CommonJS: 'seemple/class'
Реалізація класів, заснована на прототипному спадкуванні
Функція Class
дозволяє використовувати класичне ООП в тих випадках, коли немає можливості скористатися синтаксисом ECMAScript 2015 classes.
Повертає class - клас (точніше, конструктор класу)
Аргументи
Iм'я | Тип | Опис |
---|---|---|
prototype | object | Методи та властивості |
statics optional | object | Статичні методи та властивості |
Приклади
const A = Seemple.Class({
method1() { ... }
});
const B = Seemple.Class({
// B успадковується від A
extends: A,
method2() { ... }
});
const C = Seemple.Class({
// С успадковується від B
extends: B,
method2() {
// виклик батьківського методу
B.prototype.method2.apply(this, arguments);
},
method3(a, b) { ... }
});
const D = Seemple.Class({
// D успадковується від C
extends: C,
method3(a, b) {
// виклик батьківського методу
C.prototype.method2.call(this, arguments);
}
});
Передача об'єкта зі статичними методами і властивостями
const MyClass = Seemple.Class({
method() { ... }
}, {
staticProp: 'foo',
staticMethod() {
return 'bar';
}
});
alert(MyClass.staticProp); // foo
alert(MyClass.staticMethod()); // bar
Seemple.bindNode() → object
Шлях до модуля CommonJS: 'seemple/bindnode'
Пов'язує властивість об'єкта з HTML елементом
Цей статичний метод працює так само, як і Seemple#bindNode та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.bindNode(object, 'x', '.my-node');
Seemple.bindOptionalNode() → object
Шлях до модуля CommonJS: 'seemple/bindoptionalnode'
Пов'язує елемент із властивістю, але не кидає виняток, якщо аргумент node - порожній масив, undefined
або не існує
Цей статичний метод працює так само, як і Seemple#bindOptionalNode та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.bindOptionalNode(object, 'x', '.my-node');
Seemple.bindSandbox() → object
Шлях до модуля CommonJS: 'seemple/bindsandbox'
Пов'язує властивість sandbox
з елементом і одв'язує попередній елемент, якщо такий існує
Цей статичний метод працює так само, як і Seemple#bindSandbox та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.bindSandbox(object, '.my-node');
Seemple.calc() → object
Шлях до модуля CommonJS: 'seemple/calc'
Створює залежність значення одної властивості від значень інших
Цей статичний метод працює так само, як і Seemple#calc та всі його варіації, але приймає в якості першого аргументу будь JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
object.a = 40;
object.b = 2;
Seemple.calc(object, 'sum', ['a', 'b'], (a, b) => a + b);
alert(object.sum); // 42
Seemple.chain(object)
→
object
Шлях до модуля CommonJS: 'seemple/chain'
Дозволяє викликати універсальні методи ланцюгом
Функція приймає будь-який об'єкт і повертає екземпляр недоступного ззовні класу, який переймає універсальні методи, дозволяючи їх ланцюговий виклик для роботи з переданим об'єктом.
Універсальні методи - це такі методи, які одночасно є в прототипі Seemple і мають статичний аналог (наприклад, Seemple#bindNode і Seemple.bindNode).
Повертає object - Екземпляр недоступного ззовні класу
Аргументи
Iм'я | Тип | Опис |
---|---|---|
object | object function | Об'єкт |
Приклади
const object = {};
Seemple.chain(object)
.calc('a', 'b', b => b * 2)
.set('b', 3)
.bindNode('c', '.node');
// те ж саме, що і
// Seemple.calc(object, 'a', 'b', b => b * 2)
// Seemple.set(object, 'b', 3)
// Seemple.bindNode(object, 'c', '.node');
Seemple.instantiate() → object
Шлях до модуля CommonJS: 'seemple/instantiate'
Створює фіксований екземпляр класу
Цей статичний метод працює так само, як і Seemple#instantiate та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.instantiate(object, 'x', SomeClass);
object.x = { a: 42 };
alert(this.x instanceof SomeClass); // true
alert(this.x.a); // 42
Seemple.lookForBinder(node)
→
binder
Шлях до модуля CommonJS: 'seemple/lookforbinder'
Повертає байндер, відповідний елементу. Якщо байндер не знайдений, повертає undefined
. Функція перебирає Seemple.defaultBinders для пошуку байндера.
Повертає binder - binder
Аргументи
Iм'я | Тип |
---|---|
node | node |
Посилання
Приклади
const element = document.createElement('input');
element.type = 'text';
console.log(Seemple.lookForBinder(element));
// поверне приблизно такий об'єкт
{
on: 'input',
getValue() {
return this.value;
},
setValue(v) {
this.value = v;
}
}
Seemple.mediate() → object
Шлях до модуля CommonJS: 'seemple/mediate'
Трансформує значення властивості при його зміні
Цей статичний метод працює так само, як і Seemple#mediate та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.mediate(object, 'x', String);
object.x = 42;
alert(typeof object.x); // string
Seemple.off() → object
Шлях до модуля CommonJS: 'seemple/off'
Видаляє обробник події
Цей статичний метод працює так само, як і Seemple#off та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.on(object, 'foo', evt => {
//...
});
Seemple.off(object, 'foo');
Seemple.on() → object
Шлях до модуля CommonJS: 'seemple/on'
Додає обробник події
Цей статичний метод працює так само, як і Seemple#on та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.on(object, 'foo', evt => {
alert(evt.hello);
});
Seemple.trigger(object, 'foo', { hello: 'World' });
Seemple.onDebounce() → object
Шлях до модуля CommonJS: 'seemple/ondebounce'
Додатє обробник події, що викликається лише однин раз за певний проміжок часу
Цей статичний метод працює так само, як і Seemple#onDebounce та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.onDebounce(object, 'foo', evt => {
//...
});
Seemple.once() → object
Шлях до модуля CommonJS: 'seemple/once'
Додає обробник події, який може бути викликаний лише один раз
Цей статичний метод працює так само, як і Seemple#once та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.once(object, 'foo', evt => {
//...
});
Seemple.parseBindings() → $nodes
Шлях до модуля CommonJS: 'seemple/parsebindings'
Парсить DOM дерево, оголошуючи прив'язки властивостей, взятих в подвійні фігурні дужки
Цей статичний метод працює так само, як і Seemple#parseBindings та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає $nodes - Колекція оброблених DOM вузлів, передана в функцію як аргумент
Посилання
Приклади
const object = {};
const $node = Seemple.parseBindings(object, `<h3>
Hello, {{name}}
</h3>`);
object.name = 'World';
Seemple.remove() → object
Шлях до модуля CommonJS: 'seemple/remove'
Видаляє властивість
Цей статичний метод працює так само, як і Seemple#remove та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
Seemple.remove(object, 'x');
Seemple.select() → node null
Шлях до модуля CommonJS: 'seemple/select'
Повертає елемент з пісочниці, відповідний селектору
Цей статичний метод працює так само, як і Seemple#select та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає node null - знайдений елемент
Посилання
Приклади
const object = {};
Seemple.bindNode(object, 'sandbox', '.app');
Seemple.select(object, '.my-element');
Seemple.selectAll() → $nodes
Шлях до модуля CommonJS: 'seemple/selectall'
Повертає елементи з пісочниці, відповідні селектору
Цей статичний метод працює так само, як і Seemple#selectAll та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає $nodes - найденные элементы
Посилання
Приклади
const object = {};
Seemple.bindNode(object, 'sandbox', '.app');
Seemple.selectAll(object, '.my-element');
Seemple.set() → object
Шлях до модуля CommonJS: 'seemple/set'
Встановлює значення властивості, дозволяючи передати об'єкт події в якості третьої аргументу
Цей статичний метод працює так само, як і Seemple#set та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.set(object, 'x', 42, {
someOption: true
});
Seemple.toSeemple() → seemple
Шлях до модуля CommonJS: 'seemple/toseemple'
Функція, яка конвертує довільну структуру об'єктів і масивів в екземпляри Seemple.Object та Seemple.Array
Повертає seemple - новостворений екземпляр Seemple
Приклади
const seemple = Seemple.toSeemple({
a: 1,
b: {
c: 2
},
d: [{e: 1}, {e: 2}, {e: 3}]
});
Seemple.trigger() → object
Шлях до модуля CommonJS: 'seemple/trigger'
Генерує подію
Цей статичний метод працює так само, як і Seemple#trigger та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.on(object, 'foo', evt => {
alert(evt.hello);
});
Seemple.trigger(object, 'foo', { hello: 'World' });
Seemple.unbindNode() → object
Шлях до модуля CommonJS: 'seemple/unbindnode'
Розриває зв'язок між властивістю і HTML елементом
Цей статичний метод працює так само, як і Seemple#unbindNode та всі його варіації, але приймає в якості першого аргументу будь-який JavaScript об'єкт.
Повертає object - Перший аргумент
Посилання
Приклади
const object = {};
Seemple.unbindNode(object, 'x', '.my-node');
Seemple.useDOMLibrary($)
Шлях до модуля CommonJS: 'seemple/usedomlibrary'
Змушує використовувати певну бібліотеку для роботи з DOM
За замовчуванням, Seemple.js використовує в якості бібліотеки ту, яка знаходиться за посиланням window.$
. Якщо такої змінної немає в глобальному просторі імен, або ж вона не включає в себе необхідний набір методів, то використовується вбудована мікро бібліотека.
Метод useDOMLibrary
змушує фреймворк використовувати ту бібліотеку, яку ви захочете використовувати, не дивлячись на відсутність такої в глобальному просторі імен або з іншої причини (наприклад, якщо використовується дві різні версії jQuery на сторінці). Необхідно, щоб метод був запущений перед оголошенням будь-яких байндінгов.
Аргументи
Iм'я | Тип | Опис |
---|---|---|
$ | function | Будь-яка бібліотека (jQuery, Zepto, |
Приклади
Seemple.useDOMLibrary(jQuery.noConflict());
Seemple.defaultBinders: array
Шлях до модуля CommonJS: 'seemple/defaultbinders'
Масив функцій, які повертають відповідний Байндер або undefined
defaultBinders
- масив функцій, які по черзі перевіряють елемент на відповідність заданим в цих функціях правилам і повертають байндер (див. binder). Цей масив використовується тоді, коли в метод Seemple#bindNode не був переданий третій аргумент. Детальну інформацію про байндінги дивіться в документації до Seemple#bindNode.
Посилання
Приклади
Seemple.defaultBinders.unshift(element => {
// перевіряємо, чи є у елемента клас "foo"
if(element.classList.contains('foo')) {
// якщо перевірка пройдена, повертаємо новий байндер
return {
on: ...,
getValue: ...,
setValue: ...
};
}
});
// ...
this.bindNode('myKey', '.foo.bar');
Seemple.parserBrackets: object
Шлях до модуля CommonJS: 'seemple/parserbrackets'
Містить дужки для парсера
Об'єкт parserBrackets
дозволяє змінити стандартний синтаксис парсеру прив'язок. Він містить дві властивості: left
(ліва дужка, за замовчуванням "{{") і right
(права дужка, за замовчуванням "}}")
Приклади
Замінює поведінку парсеру, використовуючи синтаксис [[=property]]
замість {{property}}
Seemple.parserBrackets.left = '[[=';
Seemple.parserBrackets.right = ']]';
Seemple.binders object
Шлях до модуля CommonJS: 'seemple/binders'
Простір імен для байндерів. З коробки містить байндери загального призначення (для зв'язування атрибутів і ін.). Цей об'єкт можна розширювати власними властивостями, щоб не засмічувати глобальний простір імен.
Візьміть до уваги невелику угоду: кожна властивість з неймспейсу Seemple.binders
має бути оформлено у вигляді функції (такі функції іноді називають "binder creator"), що повертає байндер-об'єкт.
У цій документації властивості з
Seemple.binders
використовуються безпосередньо, але для поліпшення читабельності коду, рекомендується виносити їх в окремі змінні.
const html = Seemple.binders.html;
// ...
this.bindNode('x', node, html());
Або імпортувати в якості CJS модуля:
// імпорт відразу декількох байндерів
import { html, text, prop } from 'seemple/binders';
// імпорт байндерів окремо
import html from 'seemple/binders/html';
Посилання
Приклади
Seemple.binders.myCoolBinder = (var1, var2) => {
return {
on: 'click',
getValue() { ... },
setValue() { ... },
initialize() { ... },
destroy() { ... }
};
};
this.bindNode('myKey', '.my-element',
Seemple.binders.myCoolBinder('Hello', 'World'));
Seemple.binders.attr(attribute, mappingFn)
→
binder
Повертає байндер, який змінює атрибут DOM елемента на значення властивості об'єкту
Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
attribute | string | Ім'я атрибута |
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('image', 'img.my-image', Seemple.binders.attr('src'));
this.image = 'http://example.com/cats.jpg';
Використання mappingFn
this.bindNode('myKey', '.my-node',
Seemple.binders.attr('foo', value => `Hello, ${value}`));
this.myKey = 'World'; // атрибут foo має значення "Hello, World"
Seemple.binders.className(className, bool=true)
→
binder
Повертає байндер, який перемикає ім'я класу DOM елемента в залежності від значення властивості об'єкта. Якщо значення властивості нестрого дорівнює true
, ім'я класу додається, в іншому випадку - забирається. Логіку можна змінити, передавши false
другим аргументом, і, таким чином, ім'я класу буде додаватися, коли значення властивості нестрого дорівнює false
і навпаки.
Повертає binder
Аргументи
Iм'я | За замовчуванням | Тип |
---|---|---|
className |
| string |
bool optional | true
| boolean |
Приклади
this.bindNode('myKey', '.my-element',
Seemple.binders.className('blah'));
this.myKey = true; // додає клас 'blah'
this.myKey = false; // вбирає клас 'blah'
this.bindNode('myKey', '.my-element',
Seemple.binders.className('blah', false));
this.myKey = false; // додає клас 'blah'
this.myKey = true; // вбирає клас 'blah'
Seemple.binders.dataset(property, mappingFn)
→
binder
Повертає байндер, який змінює властивість dataset DOM элемента в залежності від значення властивості об'єкта.
Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
property | string | Властивість dataset |
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('myKey', '.my-element', Seemple.binders.dataset('myProp'));
this.myKey = 'foo';
Використання mappingFn
this.bindNode('myKey', '.my-element',
Seemple.binders.dataset('myProp', value => `Hello, ${value}`));
this.myKey = 'foo'; // атрибут data-my-prop має значення "Hello, foo"
Seemple.binders.display(bool=true)
→
binder
Повертає байндер для одностороннього зв'язування, який змінює видимість DOM елементу (використовуючи style.display
), в залежності від значення властивості об'єкта
Повертає binder
Аргументи
Iм'я | За замовчуванням | Тип | Опис |
---|---|---|---|
bool optional | true
| boolean | Якщо аргумент дорівнює |
Приклади
this.bindNode('myKey', '.my-element', Seemple.binders.display(true));
this.bindNode('myKey', '.my-element', Seemple.binders.display(false));
Seemple.binders.existence(bool=true)
→
binder
Повертає байндер для одностороннього зв'язування, що перемикає наявність елемента в DOM дереві, в залежності від значення властивості об'єкта
Байндер працює так само, як і Seemple.binders.display, але замість зміни видимості елемента, змінюється наявність елемента на сторінці. Байндер може бути корисним:
- Для великих додатків: в залежності від стану роутера показати ту чи іншу сторінку;
- Для реалізації нескінченного скролінгу;
- Для інших тасків, де потрібно сховати елемент, але його наявність в DOM дереві не є обов'язковою.
Повертає binder
Аргументи
Iм'я | За замовчуванням | Тип | Опис |
---|---|---|---|
bool optional | true
| boolean | Якщо аргумент дорівнює |
Приклади
this.bindNode('myKey', '.my-element', Seemple.binders.existence(true));
this.bindNode('myKey', '.my-element', Seemple.binders.existence(false));
Seemple.binders.html(mappingFn)
→
binder
Повертає байндер, який змінює innerHTML
DOM елемента в залежності від значення властивості об'єкта
Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('myKey', '.my-element', Seemple.binders.html());
// встановить innerHTML элемента як "<div>foo</div>"
this.myKey = '<div>foo</div>';
Використання mappingFn
this.bindNode('myKey', '.my-element',
Seemple.binders.html(value => `Hello, ${value}`));
// встановить innerHTML элемента як "Hello, <div>foo</div>"
this.myKey = '<div>foo</div>';
Seemple.binders.input(type)
→
binder
Повертає байндер, що зв'язує властивість об'єкта з елементом input
. Безпосередньо байндер використовувати не обов'язково, так як він входить в список Seemple.defaultBinders.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
type optional | string | Тип інпута |
Приклади
this.bindNode('myKey', '.my-input', Seemple.binders.input('range'));
Seemple.binders.output() → binder
Повертає байндер, що зв'язує властивість об'єкта з елементом output
. Безпосередньо байндер використовувати не обов'язково, так як він входить в список Seemple.defaultBinders.
Повертає binder
Приклади
this.bindNode('myKey', '.my-output', Seemple.binders.output());
Seemple.binders.progress() → binder
Повертає байндер, що зв'язує властивість об'єкта з елементом progress
. Безпосередньо байндер використовувати не обов'язково, так як він входить в список Seemple.defaultBinders.
Повертає binder
Приклади
this.bindNode('myKey', '.my-progress', Seemple.binders.progress());
Seemple.binders.prop(property, mappingFn)
→
binder
Повертає байндер, який змінює властивість DOM елемента на значення властивості об'єкта
Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
property | string | Ім'я властивості |
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('disabled', '.my-button',
Seemple.binders.prop('disabled'));
// встановлює властивість disabled = true для елемента
this.disabled = true;
// встановлює властивість disabled = false для елемента
this.disabled = false;
Використання mappingFn
this.bindNode('myProp', '.my-node'
Seemple.binders.prop('foo', value => `Hello, ${value}`));
this.myProp = 'World'; // властивість елемента foo має значення "Hello, World"
Seemple.binders.select(multiple)
→
binder
Повертає байндер, що зв'язує властивість об'єкта з елементом select
. Безпосередньо байндер використовувати не обов'язково, так як він входить в список Seemple.defaultBinders.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
multiple optional | boolean | Чи є селект |
Приклади
this.bindNode('myKey', '.my-select', Seemple.binders.select(true));
Seemple.binders.style(property, mappingFn)
→
binder
Повертає байндер, який змінює задану властивість стилю DOM елемента в залежності від значення властивості об'єкта
Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
property | string | Властивість |
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('myKey', '.my-node',
Seemple.binders.style('backgroundColor'));
this.myKey = 'red'; // колір фону .my-node став червоним
Використання mappingFn
this.bindNode('myKey', '.my-element',
Seemple.binders.style('backgroundImage', value => `url("${value}")`));
this.myKey = 'cats.jpg'; // backgroundImage дорівнює "url("cats.jpg")"
Seemple.binders.text(mappingFn)
→
binder
Повертає байндер, який змінює textContent
(текстовий вміст) DOM елемента в залежності від значення властивості об'єкта.
Seemple.binders.text
дозволяє вивести вміст властивості як є. Значення властивості можна перетворити за допомогою переданої функції mappingFn
.
Повертає binder
Аргументи
Iм'я | Тип | Опис |
---|---|---|
mappingFn optional | function | Відображаюча функція |
Приклади
this.bindNode('myKey', '.my-element', Seemple.binders.text());
this.myKey = 'foo'; // встановить textContent элемента як "foo"
Використання mappingFn
this.bindNode('myKey', '.my-element',
Seemple.binders.text(value => `Hello, ${value}`));
this.myKey = 'foo'; // встановить textContent элемента як "Hello, foo"
Seemple.binders.textarea() → binder
Повертає байндер, що зв'язує властивість об'єкта з елементом textarea
. Безпосередньо байндер використовувати не обов'язково, так як він входить в список Seemple.defaultBinders.
Повертає binder
Приклади
this.bindNode('myKey', '.my-textarea', Seemple.binders.textarea());
Клас Seemple.Object
Шлях до модуля CommonJS: 'seemple/object'
Seemple.Object
- клас, який відповідає за дані вида ключ-значення. Його завданням є відділення службових властивостей від даних, які можна передати на сервер або зберегти в локальному сховищі. Клас успадковується від класу Seemple і включає всі його властивості та методи.
Уявіть собі, що ви створюєте клас, що включає властивості "a"
, "b"
і "c"
. Припустимо "a"
і "b"
- це властивості які повинні бути відправлені на сервер, а властивість "c"
лише відповідає за деякий стан програми (наприклад, містить суму "a"
і "b"
). Властивість "c"
не повинна бути відправлена на сервер. Тому нам потрібно відокремити властивості, які відповідають за дані.
Для того, щоб відокремити такі властивості від інших, можна скористатися методом Seemple.Object#addDataKeys.
this.addDataKeys(['a', 'b']);
this.a = 1;
this.b = 2;
this.c = 3;
Якщо ви заздалегідь не знаєте, які властивості є даними, можна завжди використовувати метод Seemple.Object#setData, який не тільки оголошує властивості, що відповідають за дані, але і відразу встановлює значення.
this.setData({
a: 1,
b: 2
});
this.c = 3;
Після того, як додаток отримав інформацію про те, що є даними, екземпляр Seemple.Object можна конвертувати в звичайний об'єкт методом Seemple.Object#toJSON і передати на сервер або зберегти в локальній БД (наприклад, в localStorage
).
// поверне об'єкт { a: 1, b: 2 }
this.toJSON();
Події
При додаванні і зміні властивостей, що відповідають за дані генеруються події set
і modify
, при видаленні - remove
і modify
. Тобто будь-які зміни даних можна слухати за допомогою modify
.
this.on('modify', () => {
alert('Object is modified');
});
Аргументи
Iм'я | Тип | Опис |
---|---|---|
data optional | object | Дані, що входять в новий екземпляр |
Приклади
Створення екземпляра з двома властивостями-даними
// те ж саме, що і new Seemple.Object().setData({ a: 1, b: 2 });
new Seemple.Object({ a: 1, b: 2 });
Спадкування
class MyClass extends Seemple.Object {
constructor(data) {
super(data).sayHello();
}
sayHello() {
alert("Hello World!");
}
}
Спадкування за допомогою функції Seemple.Class
const MyClass = Seemple.Class({
extends: Seemple.Object,
constructor(data) {
this.setData(data).sayHello();
},
sayHello() {
alert("Hello World!");
}
});
Перебір даних, використовуючи цикл for..of
const seempleObject = new Seemple.Object({ a: 1, b: 2 });
for(let item of seempleObject) {
console.log(item); // 1 .. 2
}
Seemple.Object#addDataKeys(keys)
→
seempleObject
Додає задані імена властивостей в список імен властивостей, що відповідають за дані
Цей метод застосовується тоді, коли потрібно оголосити властивості, що відповідають за дані, але значення цих властивостей ще не відомі.
Повертає seempleObject - self
Генерує події set modify
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keys | string array | Масив імен властивостей або список аргументів з іменами властивостей |
Приклади
this.addDataKeys(['a', 'b']);
this.addDataKeys('a', 'b');
Seemple.Object#each(callback, thisArg)
→
seempleObject
Перебирає властивості, що відповідають за дані
Метод дуже схожий на Array.prototype.forEach
і є альтернативою циклу for..of.
Повертає seempleObject - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
callback | function | Функція, яка викликається на кожній ітерації |
thisArg optional | * | Контекст функції |
Приклади
this
.setData({ a: 1, b: 2 })
.addDataKeys('c')
.each((value, key) => {
console.log(key, value);
});
;
// >>> a 1, b 2, c undefined
Seemple.Object#entries() → array
Повертає масив пар імен і значень властивостей, що відповідають за дані
Повертає array - entries
Приклади
for(const [key, value] of this.entries()) {
console.log(key, value);
}
Seemple.Object#isDataKey(key)
→
boolean
Перевіряє, чи входить строка до списку імен властивостей, що відповідають за дані
Повертає boolean - результат перевірки
Аргументи
Iм'я | Тип |
---|---|
key | string |
Приклади
console.log(this.isDataKey('a'));
Seemple.Object#keyOf(value)
→
string
null
Шукає задане значення властивості серед властивостей, що відповідають за дані, і повертає ім'я властивості, якщо таке значення знайдено
Повертає string null - перше знайдене ім'я властивості
Аргументи
Iм'я | Тип | Опис |
---|---|---|
value | * | значення будь-якого типу, яке слід знайти серед даних |
Приклади
const seempleObject = new Seemple.Object({
a: 1,
b: 2
});
seempleObject.c = 3;
seempleObject.keyOf(1); // 'a'
seempleObject.keyOf(2); // 'b'
seempleObject.keyOf(3); // null
Seemple.Object#keys() → array
Повертає масив імен властивостей, що відповідають за дані
Повертає array - keys
Приклади
const keys = this.keys();
Seemple.Object#removeDataKeys(keys)
→
seempleObject
Видаляє задані імена властивостей зі списку імен властивостей, що відповідають за дані (але не видаляє властивість)
Повертає seempleObject - self
Генерує події remove modify
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keys | string array | Масив імен властивостей або список аргументів з іменами властивостей |
Приклади
this.removeDataKeys(['a', 'b']);
this.removeDataKeys('a', 'b');
Seemple.Object#setData(key, value, eventOptions)
→
seempleObject
Синонім: Seemple.Object#jset
Встановлює значення властивості і додає його ім'я в список імен властивостей, що відповідають за дані
Цей метод робить дві речі:
Встановлює значення заданої властивості.
Додає ключ властивості в список даних, що робить властивість доступною для використання в методах Seemple.Object#each, Seemple.Object#keys, Seemple.Object#toJSON) та інших.
Якщо передати прапор
replaceData
, встановлений якtrue
, в об'єкт події, то інші властивості будуть вилучені зі списку властивостей, що відповідають за дані.
В іншому, метод працює так само, як і Seemple#set.
Повертає seempleObject - self
Генерує події change change:KEY modify set
Аргументи
Iм'я | Тип | Опис |
---|---|---|
key | string | Ключ |
value | * | Значення |
eventOptions optional | eventOptions | Об'єкт події |
Посилання
Приклади
this.setData('a', 1).setData('b', 2);
// Присвоювання властивості 'c' трійку,
// але не додаємо ключ 'c' в список ключів, що відповідають за дані
this.set('c', 3);
this.each((value, key) => {
console.log(key, value);
});
// виводить 'a' 1 і 'b' 2
console.log(this.keys()); // виводить ['a', 'b']
console.log(this.toJSON()); // виводить { a: 1, b: 2 }
Після використання методу setData
з властивістю можна працювати, як із звичайною властивістю
this.setData('a', 1).setData('b', 2);
this.set('a', 3);
this.b = 4;
Використання альтернативного імені методу: jset
this.jset('a', 1);
Seemple.Object#setData(keyValuePairs, evtOpts)
→
seempleObject
Альтернативний синтаксис методу Seemple.Object#setData, який приймає об'єкт ключ-значення для встановлення декількох властивостей одночасно
Повертає seempleObject - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
keyValuePairs | object | Об'єкт ключ-значення |
evtOpts | eventOptions | Об'єкт події |
Приклади
this.setData({
a: 1,
b: 2
});
Якщо передати прапор replaceData
, встановлений як true
в об'єкт події, то властивості, які не входять до переданого об'єкту, будуть вилучені зі списку властивостей, що відповідають за дані
this
.addDataKeys(['a', 'b', 'c'])
.setData({
a: 1,
b: 2
}, {
replaceData: true
});
console.log(this.keys()); // ['a', 'b']
Seemple.Object#toJSON(recursive=true)
→
object
Конвертує екземпляр Seemple.Object в звичайний об'єкт
Метод працює рекурсивно, викликаючи toJSON
для всіх властивостей, у яких є метод з таким ім'ям. Для скасування рекурсії передайте false
першим аргументом.
Повертає object
Аргументи
Iм'я | За замовчуванням | Тип |
---|---|---|
recursive optional | true
| boolean |
Приклади
const seempleObject = new Seemple.Object({
a: 1,
b: 2,
c: new Seemple.Object({
d: 3,
e: 4
})
});
// повертає {a: 1, b: 2, c: { d: 3, e: 4 }}
console.log(seempleObject.toJSON());
// повертає {a: 1, b: 2, c: SeempleObject}
console.log(seempleObject.toJSON(false));
Seemple.Object#values() → array
Повертає масив значень властивостей, що відповідають за дані
Повертає array - values
Приклади
const values = this.values();
Seemple.Object#isSeempleObject: boolean
Властивість isSeempleObject
завжди дорівнює true
для екземплярів Seemple.Object.
Приклади
console.log(object.isSeempleObject);
Клас Seemple.Array
Шлях до модуля CommonJS: 'seemple/array'
Клас Seemple.Array
служить колекцією в Seemple.js. Він успадковується від класу Seemple і включає всі його властивості та методи. Крім цього, Seemple.Array
має всі методи, які є у звичайного масиву, тим самим спрощуючи вивчення його можливостей.
Всі методи, запозичені у вбудованого Array працюють аналогічно їх оригіналам
Програміст, знайомий з методами нативного Array
відразу може зрозуміти, яким методом можна додати елемент (push
, unshift
, splice
), яким видалити (pop
, shift
, splice
), яким впорядкувати (sort
, reverse
) тощо.
У зв'язку з тим, що методи працюють так само, як і оригінальні (з невеликими винятками), вони не приведені в цій документації окремо, а виведені в розділ Seemple.Array#METHOD.
this.push(1, 2, 3);
this.pop();
Всі методи, запозичені у вбудованого Array, які модифікують масив можуть бути викликані з передачею об'єкта події
Для цього використовується синтаксис метод_
, де нижнє підкреслення в кінці імені методу означає, що останнім аргументом є об'єкт події. Такі методи не наведено в цій документації, так як потрібно запам'ятати тільки їх синтаксис. Див. Seemple.Array#METHOD_.
this.push_(1, 2, 3, {
silent: true
});
this.pop_({
foo: 'bar'
});
Розробник має можливість відловлювати будь-які модифікації даних
При використанні методів, запозичених у вбудованого Array
генеруються події з відповідним ім'ям. Викликаючи метод push
, генерується подія push
, викликаючи метод shift
генерується подія shift
, викликаючи метод sort
, генерується подія sort
і так далі.
this.on('push', evt => {
console.log('push is called');
});
this.push(1, 2, 3);
При додаванні елементів генеруються події add
і addone
. Перше генерується один раз на додавання (наприклад, ви додали кілька елементів за допомогою push
, подія викликана лише один раз), друге генерується один раз на кожен доданий елемент.
При спрацьовуванні події add
, значенням властивості added
об'єкта події передається масив доданих елементів, а при спрацьовуванні addone
, значенням властивості addedItem
- кожен окремий доданий елемент.
this.on('add', evt => {
console.log(evt.added); // [1,2,3]
});
this.push(1, 2, 3);
// Обробник запуститься тричі,
// так як в масив додали три нові елементи
this.on('addone', evt {
console.log(evt.addedItem); // 1 ... 2 ... 3
});
this.push(1, 2, 3);
При видаленні елементів діє та ж логіка: remove
спрацьовує один раз, навіть якщо видалено кілька елементів, а подія removeone
спрацьовує для кожного віддаленого елемента індивідуально. При генерації події remove
вилучені елементи містяться у властивості removed
об'єкта події, а при генерації події removeone
- кожен віддалений елемент міститься у властивості removedItem
.
this.push(1, 2, 3, 4, 5);
this.on('remove', evt => {
console.log(evt.removed); // [2, 3, 4]
});
this.splice(1, 3);
this.push(1, 2, 3, 4, 5);
// Обробник запуститься тричі,
// так як з масиву видалили три елементи
this.on('removeone', evt => {
console.log(evt.removedItem); // 2 ... 3 ... 4
});
this.splice(1, 3);
Приі кожної модифікації масиву генерується подія modify
, дозволяючи відловити всі без винятку зміни в масиві (додавання, видалення, пересортовування).
this.on('modify', evt => {
console.log(evt.added);
console.log(evt.removed);
});
length
- це звичайне свойство яке можна пов'язувати з HTML елементом або відловлювати зміни за допомогою події change:length
.
Наприклад, при додаванні трьох елементів за допомогою методу
push
, генеруються наступні події:push
,add
,addone
(тричі),modify
,change:length
.
Model
Властивість Seemple.Array#Model визначає клас елементів, які буде містити колекція. Рекомендується наслідувати Model
від класу Seemple.Object або Seemple.Array (на випадок, якщо потрібно отримати колекцію колекцій), щоб отримати можливість конвертації масиву в звичайний масив рекурсивно методом Seemple.Array#toJSON.
Автоматичний рендеринг
Seemple.Array
вміє автоматично відмальовувати елементи на сторінці при будь-яких модифікаціях масиву. За подробицями зверніться до документації Seemple.Array#itemRenderer.
Посилання
Приклади
Створення екземпляра з нульовою довжиною
new Seemple.Array();
Створення екземпляра із зазначенням довжини
new Seemple.Array(42);
Передача елементів при створенні
new Seemple.Array('Hi', { a: 'b' });
Спадкування
class MyClass extends Seemple.Array {
constructor(items) {
super(...items).sayHello();
}
sayHello() {
alert("Hello World!");
}
}
Спадкування, використовуючи функцію Seemple.Class
const MyClass = Seemple.Class({
extends: Seemple.Array,
constructor(items) {
this.recreate(items).sayHello();
},
sayHello() {
alert("Hello World!");
}
});
Seemple.Array#METHOD()
Будь-який метод iз Array.prototype
Seemple.Array включає в себе всі методи, що входять в нативний JavaScript масив:
- join
- pop
- push
- reverse
- shift
- unshift
- slice
- splice
- sort
- filter
- forEach
- some
- every
- map
- indexOf
- lastIndexOf
- reduce
- reduceRight
- copyWithin
- find
- findIndex
- fill
- includes
- entries
- keys
- concat
При цьому, вони працюють точно так же, як і методи Array.prototype
. Є лише кілька застережень:
- Метод
forEach
повертає себе замістьundefined
- Методи, які в оригінальному вигляді повертають новий масив (
splice
,slice
,filter
,map
...), повертають новий екземплярSeemple.Array
. - Методи
keys
,values
таentries
повертають масив замість ітератора.
Крім усього, методи генерують події пов'язані з будь-якою модифікацією масиву. Детальніше див. Seemple.Array.
Посилання
Приклади
this.push(1, 2, 3);
const seempleArray = this
.forEach((value, index) => {
//...
})
.map((value, index) => {
//...
});
console.log(seempleArray.isSeempleArray); // true
this.reverse();
Seemple.Array#METHOD_()
Будь-який метод iз Array.prototype
з можливістю передати об'єкт події
Ознайомившись з Seemple.Array#METHOD стає зрозуміло, що методи не підтримують передачу об'єкта події, так як в точності повторюють синтаксис і кількість аргументів методів вбудованого Array
. Синтаксис МЕТОД_
дозволяє передати в обробник події якісь дані або встановити службові прапори, що відповідають за поведінку масиву після виклику методу.
Службові прапори:
Посилання
Приклади
this.push_(1, 2, 3, {
silent: true
});
this.pop_({
silent: true
});
this.on('modify', evt => {
alert(evt.flag); // 42
});
this.push_(1, 2, 3, {
flag: 42
});
<virtual>Seemple.Array#Model(data, seempleArray, index)
Властивість визначає клас елементів, які буде містити колекція
При кожному додаванні елементів в масив, вбудований обробник перевіряє, чи є доданий елемент екземпляром Model
і конвертує його в такий, якщо перевірка не пройдена. Рекомендується наслідувати Model
від класу Seemple.Object або Seemple.Array (на випадок, якщо потрібно отримати колекцію колекцій), щоб отримати можливість конвертації масиву в звичайний масив методом Seemple.Array#toJSON.
Для більш гнучкого контролю класу елементів (наприклад, якщо для одних елементів потрібно використовувати одну "модель", а для інших - іншу), використовуйте Seemple.Array#mediateItem.
Аргументи
Iм'я | Тип | Опис |
---|---|---|
data | object | Дані, передані в конструктор |
seempleArray | seempleArray | Масив, в який додали елемент |
index | number | Поточний індекс об'єкта в батьківському масиві |
Посилання
Приклади
// визначаємо "модель"
class MyModel extends Seemple.Object {
constructor(data, parentArray, index) {
super(data);
this.doSomething();
}
doSomething() { ... }
}
// визначаємо клас для колекції
class MyArray extends Seemple.Array {
get Model() {
return MyModel;
}
}
// створюємо екземпляр класу
const myArray = new MyArray();
// додаємо два елементи
myArray.push({
a: 1,
b: 2
}, {
a: 3,
b: 4
});
console.log(myArray[0] instanceof MyModel); // true
console.log(myArray[1] instanceof MyModel); // true
// поверне [{ a: 1, b: 2 }, { a: 3, b: 4 }]
myArray.toJSON();
Seemple.Array#mediateItem(mediator)
Трансформує значення елементів масиву
Цей метод служить для того, щоб перехопити і трансформувати додані в масив елементи. Зверніть увагу, метод перевизначає властивість Seemple.Array#Model.
Аргументи
Iм'я | Тип | Опис |
---|---|---|
mediator | function | Функція, що повертає трансформований елемент масиву |
Посилання
Приклади
// всі елементи масиву - цілі числа
this.mediateItem(item => parseInt(item) || 0);
this.push(1, 2, 3, 4, 5);
// всі елементи масиву - строки
this.mediateItem(String);
this.push(6, 7);
this.unshift(true, {});
// ["true", "[object Object]", "1", "2", "3", "4", "5", "6", "7"]
console.log(seempleArray.toJSON());
this.mediateItem(item => {
if(item.something) {
return new FirstModel(item);
} else {
return new SecondModel(item);
}
});
<virtual>Seemple.Array#onItemRender(item, renderEvent)
Функція, яка запускається перед подією render
.
Віртуальний метод onItemRender
можна використовувати в якості заміни події render
.
При цьому, у вставленого айтема викликається віртуальний метод onRender
з єдиним аргументом - об'єктом події.
Аргументи
Iм'я | Тип | Опис |
---|---|---|
item | object | Елемент колекції |
renderEvent | object | Об'єкт події |
Приклади
class MyModel extends Seemple.Object {
constructor(data) {
super(data);
}
onRender(renderEvt) {
this.bindNode('isChecked', ':sandbox .my-checkbox');
this.bindNode('text', ':sandbox .text', Seemple.binders.html());
}
});
class MyArray extends Seemple.Array {
get Model() {
return MyModel;
}
itemRenderer() {
return '<li>'
}
constructor() {
this.bindNode('sandbox', '.my-form');
}
onItemRender(item, renderEvt) {
// ...
}
});
const app = new MyArray();
Seemple.Array#orderBy(keys, orders=asc)
→
seempleArray
Сортує масив за значеннями властивостей об'єктів, які в нього входять
Цей метод працює майже так само, як і метод orderBy з lodash. Він приймає ключ або масив ключів першим аргументом, порядок (asc/desc) або масив порядків - другим.
Повертає seempleArray - self
Генерує події sort
Аргументи
Iм'я | За замовчуванням | Тип | Опис |
---|---|---|---|
keys |
| string array | Ключ властивості або масив декількох ключів, за якими колекція буде відсортована |
orders optional | asc
| string array | Порядок або масив порядків, відповідних до масиву ключів |
Приклади
this.recreate([
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 34 },
{ 'user': 'fred', 'age': 42 },
{ 'user': 'barney', 'age': 36 }
]);
// сортує за значенням властивості 'user' по зростанню і значенням властивості 'age' по спаданню
this.orderBy(['user', 'age'], ['asc', 'desc']);
// → [{"user":"barney","age":36},{"user":"barney","age":34},{"user":"fred","age":48},{"user":"fred","age":42}]
Seemple.Array#pull(indexOrValue, eventOptions)
→
*
null
Видаляє елемент за індексом або за значенням
Повертає * null - Видалений елемент або null
Генерує події pull remove removeone modify
Аргументи
Iм'я | Тип | Опис |
---|---|---|
indexOrValue | object number | Індекс елемента, який потрібно видалити або видаляємий об'єкт |
eventOptions optional | eventOptions | Об'єкт події на випадок, якщо потрібно передати в обробник події якісь дані або встановити службові прапори (наприклад, |
Приклади
Передача індексу масиву
let removed;
this.recreate(['a', 'b', 'c']);
removed = this.pull(1);
console.log(removed); // 'b'
console.log(this.join(',')); // 'a,c'
Передача видаляємого об'єкту
const object1 = {};
const object2 = {};
const object3 = {};
let removed;
this.push(object1, object2, object3);
removed = this.pull(object2);
console.log(removed === object2); // true
console.log(this.length); // 2
Seemple.Array#recreate(array, eventOptions)
→
seempleArray
Перестворює екземпляр Seemple.Array
Метод дозволяє конвертувати будь-який масив (або об'єкт, подібний масиву) в екземпляр Seemple.Array. Якщо нічого не передано в якості першого аргументу, екземпляр очищується.
Повертає seempleArray - self
Генерує події recreate modify add addone remove removeone
Аргументи
Iм'я | Тип | Опис |
---|---|---|
array optional | array | Масив або масивоподібний об'єкт |
eventOptions optional | eventOptions | Об'єкт події |
Посилання
Приклади
// очищаємо масив і додаємо 5 нових айтемів
this.recreate([1, 2, 3, 4, 5]);
// очищаємо масив
this.recreate();
Seemple.Array#rerender(eventOptions)
→
seempleArray
Перемальовує DOM вузли об'єктів, що входять в масив
Цей метод заново рендерить елементи масиву в контейнері масиву. Якщо вузол, який асоційований з айтемом вже створений, метод, замість перемальовування з нуля, "перевставляє" його в контейнер масиву.
Метод може бути корисним на випадок, коли елементи додані в масив перед оголошенням контейнера.
Щоб змусити масив перемалюватися, незалежно від наявності відрендерених вузлів (наприклад, ви використовуєте кастомний шаблонізатор в itemRenderer
), передайте в метод об'єкт з властивістю forceRerender
рівною true
.
Повертає seempleArray - self
Аргументи
Iм'я | Тип | Опис |
---|---|---|
eventOptions optional | eventOptions | Об'єкт події |
Приклади
this.rerender({
forceRerender: true
});
Seemple.Array#restore(selector, eventOptions)
→
seempleArray
Відтворює Seemple.Array з HTML вузлів на сторінці.
У разі, якщо колекція заздалегідь відмальована на сторінці (наприклад, за допомогою сервера), метод може відтворити колекцію з HTML вузлів.
<!-- One, Two, Three заздалегідь відмальовані -->
<ul class="collection-node">
<li>One</li>
<li>Two</li>
<li>Three</li>
<script type="text/html" class="renderer">
<li></li>
</script>
</ul>
class MyModel extends Seemple.Object {
constructor(data) {
super(data);
this.addDataKeys('value');
}
onRender() {
this.bindNode('value', ':sandbox', Seemple.binders.html())
}
});
class MyCollection extends Seemple.Array {
get itemRenderer() {
return ':sandbox .renderer';
}
constructor() {
this
.bindNode('sandbox', '.collection-node')
.restore(':sandbox li');
}
});
const myCollection = new MyCollection();
myCollection.push({
value: 'Four'
});
console.log(myCollection.toJSON());
// [{value: 'One'}, {value: 'Two'}, {value: 'Three'}, {value: 'Four'}]
Якщо аргумент selector
не заданий, то колекція буде відтворена з елементів, що входять в контейнер ("container"
або "sandbox"
).
При відтворенні, на кожному елементі масиву генерується подія render
і викликаються методи onRender
і onItemRender
(див документацію), як і при звичайному рендерингу.
Повертає seempleArray - self
Генерує події recreate modify add addone
Аргументи
Iм'я | Тип | Опис |
---|---|---|
selector optional | selector | Селектор |
eventOptions optional | eventOptions | Об'єкт події |
Seemple.Array#toJSON(recursive=true)
→
array
Конвертує екземпляр Seemple.Array в звичайний масив
Метод працює рекурсивно, викликаючи toJSON
для внутрішніх об'єктів, у яких є метод з таким ім'ям. Для скасування рекурсії передайте false
першим аргументом.
Повертає array
Аргументи
Iм'я | За замовчуванням | Тип |
---|---|---|
recursive optional | true
| boolean |
Приклади
const seempleArray = new Seemple.Array([1, 2, new SeempleArray(3, 4)]);
// повертає [1, 2, [3, 4]]
console.log(seempleArray.toJSON());
// повертає [1, 2, SeempleArray]
console.log(seempleArray.toJSON(false));
Seemple.Array#isSeempleArray: boolean
isSeempleArray
завжди дорівнює true
для экземплярів Seemple.Array
Приклади
console.log(object.isSeempleArray);
<virtual>Seemple.Array#itemRenderer: string function
HTML строка, селектор або функція, яка відповідає за рендерінг элементів масива на сторінці
Властивість itemRenderer
- це перевизначаєма (віртуальна) властивість, яка дозволяє рендерити айтеми масиву без додаткового коду. При вставці нового об'єкта в масив, автоматично створюється HTML елемент. Цей елемент стає пісочницею (див. Seemple#bindNode) (цю поведінку можна скасувати, див. нижче) для вставленого об'єкта і вставляється в HTML контейнер, визначений у масиві.
Для скорочення, в прикладах до цієї статті буде використовуватися синтаксис class fields.
Куди вставляється створений елемент?
Для того, щоб визначити місце, в яке будуть вставлятися відмальовані HTML вузли, потрібно визначити *контейнер *. Для цього слід оголосити HTML пісочницю для масиву або зв'язати спеціальний ключ container
з HTML контейнером. Детальніше про привязки і пісочницю див. Seemple#bindNode.
Приклад використання пісочниці як контейнера:
<ul class="my-list"></ul>
class MyArray extends Seemple.Array {
itemRenderer = '<li>';
get Model() { return MyModel; }
constructor() {
super();
// визначаємо пісочницю
this.bindNode('sandbox', '.my-list');
}
});
Тепер всі новостворені елементи <li>
попадуть у елемент .my-list
.
Якщо ви не хочете вставляти HTML елементи безпосередньо в пісочницю, можете пов'язати ключ container
з необхідним контейнером. Така логіка потрібна в тому випадку, якщо пісочниця не обмежена одними лише елементами колекції і включає в себе інші HTML елементи.
<div class="my-widget">
<h1>This is my awesome list</h1>
<ul class="my-list"></ul>
</div>
class MyArray extends Seemple.Array {
itemRenderer = '<li>';
get Model() { return MyModel; }
constructor() {
super();
// визначаємо пісочницю
this.bindNode('sandbox', '.my-widget');
// визначаємо контейнер для HTML элементів
this.bindNode('container', '.my-list');
}
}
В наведеному вище прикладі HTML вузли попадуть в .my-list
замість .my-widget
.
Властивість itemRenderer
підтримує кілька варіантів визначення, але всі вони повинні містити або повертати єдиний HTML вузол.
HTML строка в якості значення властивості
Як видно з прикладу вище, itemRenderer
може бути визначений, як HTML строка.
class MyArray extends Seemple.Array {
get Model() { return MyModel; }
itemRenderer = '<div class="my-div">foo</div>';
constructor() { ... }
}
Селектор в якості значення властивості
На випадок, якщо ви виносите шаблони для елементів на HTML сторінку, itemRenderer
підтримує селектор в якості значення. У цьому випадку, Seemple.Array буде шукати HTML елемент в DOM дереві і витягне innerHTML
знайденого елемента. У разі, якщо елемент не знайдений, кидається виняток.
HTML текст від селектора відрізняється наявністю символу
<
.
<script type="text/html" id="my-template">
<div class="my-div">foo</div>
</script>
class MyArray extends Seemple.Array {
get Model() { return MyModel; }
itemRenderer = '#my-template';
constructor() { ... }
}
Функція як значення властивості
Використання функції в якості значення властивості itemRenderer
може стати в нагоді, коли є потреба динамічно генерувати елемент для рендеринга. Функція може повертати:
HTML строку
class MyArray extends Seemple.Array {
itemRenderer() {
return '<div class="my-div">foo</div>';
}
}
Селектор
class MyArray extends Seemple.Array {
itemRenderer: function() {
return '#my-template';
}
}
DOM вузол
class MyArray extends Seemple.Array {
itemRenderer() {
return document.createElement('div');
}
}
Перекриття батьківського рендерера властивістю render
Іноді зручно оголошувати рендерер в класі Seemple.Array#Model, а не на рівні колекції. Властивість renderer
перекриває значення itemRenderer
, якщо вона задана для елемента колекції.
class MyModel extends Seemple.Object {
renderer = '<div class="my-div">foo</div>';
}
class MyArray extends Seemple.Array {
Model = MyModel,
itemRenderer = '<frameset>bar</frameset>';
constructor() { ... }
}
В цьому випадку, можна зовсім не вказувати itemRenderer
, так як render
дочірнього елемента переймає всі його можливості. Синтаксис залишається таким же: можна використовувати HTML, селектор або функцію.
Події render
та afterrender
Після того, як об'єкт вставлений в масив, а його HTML елемент вже створений, але ще не вставлений в контейнер, генерується подія render
на вставленому об'єкті. Після його генерації можна оголосити прив'язки властивостей до HTML вузлів, що містяться всередині цього елемента.
afterrender
, в свою чергу, генерирується після вставки HTML элемента в контейнер масива.
<form class="my-form"></form>
class MyModel extends Seemple.Object {
constructor(data) {
super(data);
// чекаємо на генерацію події
this.on('render', () => {
// оголошуємо біндінги
this.bindNode('isChecked', ':sandbox .my-checkbox');
this.bindNode('text', ':sandbox .text',
Seemple.binders.html());
});
}
});
class MyArray extends Seemple.Array {
get Model() { return MyModel; }
itemRenderer = `<label>
<input type="checkbox" class="my-checkbox">
<span class="text"></span>
</label>`;
constructor() {
super();
this.bindNode('sandbox', '.my-form');
this.push({
isChecked: true,
text: 'Buy a raccoon'
}, {
isChecked: false,
text: 'Sell the raccoon'
});
}
});
const app = new MyArray();
Код вище створить таке HTML дерево:
<form class="my-form">
<label>
<input type="checkbox" class="my-checkbox">
<span class="text">Buy a raccoon</span>
</label>
<label>
<input type="checkbox" class="my-checkbox">
<span class="text">Sell the raccoon</span>
</label>
</form>
І зв'яже чекбокси з відповідними властивостями isChecked
і text
.
Не забувайте, що в Seemple.js реалізована можливість вилову делегованих подій. Тобто сам масив може відловити подію рендеринга айтема, використовуючи ім'я події *@render
(див. документацію до eventNames).
this.on('*@render', () => {
alert('Child element is rendered');
});
HTML елемент стає пісочницею для вставленого об'єкту дозволяючи використовувати селектор
:sandbox
і інші можливості після рендеринга. Якщо об'єкт входить відразу в кілька колекцій, встановіть йому властивістьbindRenderedAsSandbox: false
, щоб скасувати цю поведінку.
class MyModel extends Seemple.Object {
bindRenderedAsSandbox = false;
// ...
});
onItemRender
та onRender
Для поліпшення коду в одній з попередніх версій з'явився віртуальний метод Seemple.Array#onItemRender, який можна використовувати замість події render
. В якості альтернативи, у "моделей" викликається метод onRender
, що так само дозволяє зробити код більш "плоским" і позбутися вкладених функцій.
class MyModel extends Seemple.Object {
constructor(data) {
super(data);
}
onRender(evt) {
this.bindNode('isChecked', ':sandbox .my-checkbox');
this.bindNode('text', ':sandbox .text',
Seemple.binders.html());
}
}
class MyArray extends Seemple.Array {
get Model() { return MyModel; }
itemRenderer = '...';
constructor() {
//...
},
onItemRender(item, evt) {
//...
}
}
const app = new MyArray();
Шаблонізатор
Поглянувши на приклади використання Seemple.Array і Seemple.Array#itemRenderer можна звернути увагу на те, що вся логіка, що відповідає за двосторонню і односторонню прив'язку даних укладена в JavaScript коді. Але коли розробляєш дуже просту колекцію, яка не включає в себе складну логіку, масу прив'язок та ін. хотілося б мати більш короткий варіант оголошення прив'язок. Для цього, в itemRenderer
може бути переданий шаблон, що включає прив'язки, укладені у фігурні дужки (див. Seemple#parseBindings).
class MyArray extends Seemple.Array {
itemRenderer: `<label>
<input type="checkbox" checked="{{isChecked}}">{{text}}
</label>`
// ...
}
const app = new MyArray();
Скасування рендеринга
Як видно вище, якщо у дочірнього елемента задано властивість render
, Seemple.Array
спробує його змалювати. Для того, щоб повністю скасувати рендеринг для масиву, надайте властивості масиву renderIfPossible
значення false
.
class MyArray extends Seemple.Array {
renderIfPossible = false;
// ...
}
Переміщення об'єкта з одного масиву в інший
За замовчуванням, при вставці об'єкта в масив Seemple.js спробує його змалювати, використовуючи itemRenderer
. Це дає перевагу у випадках, коли у вас на сторінці є два або більше контейнерів, що включають в себе елементи прив'язані до одного і того же об'єкту. При зміні об'єкта, всі елементи реагують на зміну, оновлюючи DOM.
Але іноді стоїть завдання переміщення об'єкта між колекціями, не перемальовуючи його заново. Для переміщення об'єкта з одного масиву в інший, включаючи його пісочницю, використовуйте прапор moveSandbox
.
this.push_(item, {
moveSandbox: true
});
Перевизначення itemRenderer
При перевизначенні властивості itemRenderer
, колекція автоматично перемальовується.
this.itemRenderer = '<div>';
Ця можливість корисна в тому випадку, коли розробник бажає завантажити шаблон з сервера.
fetch('templates/template.html')
.then(resp => resp.text())
.then(data => {
this.itemRenderer = data;
});
Для рендеринга тільки тих об'єктів, які ще не були намальовані, скористайтеся методом Seemple#set з прапором forceRerender
зі значенням false
this.set('itemRenderer', renderer, {
forceRerender: false
});
Така необхідність може виникнути тоді, коли ви використовуєте серверний пререндерінг (див. Seemple.Array#restore), а шаблон завантажується динамічно.
class MyArray extends Seemple.Array {
constructor() {
super()
.bindNode('sandbox', '.some-node')
.restore();
fetch('templates/template.html')
.then(resp => resp.text())
.then(data => {
this.set('itemRenderer', data, {
forceRerender: false
});
});
}
}
Рендерінг колекції, що складається зі звичайних об'єктів
Об'єкт, що входить в колекцію, не обов'язково повинен бути екземпляром Seemple
, можна рендерити будь-який об'єкт. Байндінги для таких об'єктів можна оголосити використовуючи статичний метод Seemple.bindNode.
class MyArray extends Seemple.Array {
// Model не визначена
itemRenderer: ...
onItemRender(item) {
Seemple.bindNode(item, 'x', ':sandbox .some-node');
}
})
Ще невеликий приклад: рендеринг простого списку.
class MyArray extends Seemple.Array {
itemRenderer = '<li>{{value}}</li>';
constructor() {
super().bindNode('sandbox', '.my-list');
}
});
const arr = new MyArray();
arr.push({ value: 'Item 1' }, { value: 'Item 2' });
Посилання
Seemple.Array#renderIfPossible: boolean
Властивість renderIfPossible
скасовує рендеринг масиву якщо має значення false
Посилання
Приклади
class MyArray extends Seemple.Array {
get renderIfPossible() {
return false;
}
// ...
});
<virtual>Seemple.Array#trackBy: string
Властивість trackBy
вказує на ім'я властивості ідентифікатора об'єктів, що входять в масив
У разі, якщо клієнт і сервер активно обмінюються даними (наприклад, списком користувачів), а об'єкти, що входять в масив мають унікальний ID (наприклад, ідентифікатор користувача), то перерисовка всієї колекції з нуля не має сенсу. Після того, як сервер повернув нову колекцію, набагато раціональніше перевірити, чи є в колекції об'єкт з таким само ID і, якщо об'єкт знайдений, оновити його. Таким чином, не створюється новий об'єкт (екземпляр Seemple.Array#Model) і не створюється новий DOM вузол.
trackBy
працює тільки при використанні методу Seemple.Array#recreate, так як це єдиний метод який "перестворює" колекцію заново.
У прикладі нижче використовується _id
як ключ ідентифікатора.
class MyArray extends Seemple.Array {
get trackBy() {
return '_id';
}
constructor() {
//...
}
});
const arr = new MyArray();
// додає два об'єкти в масив
arr.recreate([
{_id: 0, name: 'Foo'},
{_id: 1, name: 'Bar'},
{_id: 2, name: 'Baz'}
]);
// Видалить об'єкт з ідентифікатором 0
// Додасть об'єкт з ідентифікатором 3
// Оновить об'єкт з ідентифікатором 1, перезаписавши name: Bar -> BarNew
// Оновить об'єкт з ідентифікатором 2, перезаписавши name: Baz -> BazNew
// Пересорує колекцію у відповідності з переданим даними
arr.recreate([
{_id: 1, name: 'BarNew'},
{_id: 3, name: 'Qux'},
{_id: 2, name: 'BazNew'}
]);
Властивість може містити спеціальне значення "$index"
, яке дозволяє оновлювати об'єкт за індексом в колекції.
class MyArray extends Seemple.Array {
get trackBy() {
return '$index';
}
constructor() {
//...
}
});
const arr = new MyArray();
// додасть два об'єкти в масив
arr.recreate([
{name: 'Foo'},
{name: 'Bar'},
{name: 'Baz'}
]);
// оновить всі три об'єкти новими даними
// і додасть новий об'єкт з ім'ям Qux
arr.recreate([
{name: 'NewFoo'},
{name: 'NewBar'},
{name: 'NewBaz'},
{name: 'Qux'}
]);
Посилання
Seemple.Array.from(arrayLike, mapFn, thisArg)
→
seempleArray
Метод створює новий екземпляр Seemple.Array з масивоподібного або ітеруємого об'єкта
Повертає seempleArray
Аргументи
Iм'я | Тип | Опис |
---|---|---|
arrayLike | object | Массивоподібний або ітеруємий об'єкт |
mapFn optional | function | Відображаюча функція, що викликається для кожного елемента масиву |
thisArg optional | * | Об'єкт, який використовується в якості |
Посилання
Приклади
const seempleArray = Seemple.Array.from([1, 2, 3, 4]);
const seempleArray = Seemple.Array.from([1, 2, 3, 4], item => item * 2);
Спадкування методу
class MyClass extends Seemple.Array {
// ...
}
const myArray = MyClass.from([1, 2, 3, 4]);
console.log(myArray instanceof MyClass); // true
Seemple.Array.of() → seempleArray
Метод створює новий екземпляр Seemple.Array з довільного числа агрумент, незалежно від числа або типу аргументів
Повертає seempleArray
Посилання
Приклади
const seempleArray = Seemple.Array.of(1, 2, 3, 4);
Спадкування методу
class MyClass extends Seemple.Array {
// ...
}
const myArray = MyClass.of(1, 2, 3, 4);
console.log(myArray instanceof MyClass); // true
eventHandler: function
Функція-обробник події. Приймає будь-які аргументи, передані в Seemple#trigger
Аргументи
Iм'я | Тип | Опис |
---|---|---|
options | * | будь-які аргументи, передані в виклик Seemple#trigger після імені події |
Приклади
const eventHandler = (...args) => {
console.log(args);
};
this.on('fyeah', eventHandler);
// logs 'foo', 'bar', 'baz'
this.trigger('fyeah', 'foo', 'bar', 'baz');
seemple: object
Екземпляр класу Seemple
Приклади
const seemple = new Seemple();
obj.calc('a', 'b');
seempleObject: object
Екземпляр класу Seemple.Object
Приклади
const obj = new Seemple.Object({ foo: 'x' });
obj.setData({ bar: 'y' });
seempleArray: object
Екземпляр класу Seemple.Array
Приклади
const arr = new Seemple.Array(1, 2, 3);
arr.push(4);
eventNames: string
Ім'я події або кілька імен, розділених пробілами.
Довільні події
this.on('myevent', () => {...});
this.trigger('myevent');
change:KEY
, що викликається, коли властивість змінюється
this.on('change:x', evt => {...});
this.x = 42;
beforechange:KEY
, що викликається, перед зміною властивості
this.on('beforechange:x', evt => {...});
this.x = 42;
addevent:NAME
і addevent
, що викликаються, коли подія ініціалізується
// для всіх подій
this.on('addevent', evt => {...});
// для події "someevent"
this.on('addevent:someevent', evt => {...});
// генерує події "addevent" та "addevent:someevent"
this.on('someevent', evt => {...});
removeevent:NAME
і removeevent
, що викликаються, коли обробник події видаляється
// для всіх подій
this.on('removeevent', evt => {...});
// для події "someevent"
this.on('removeevent:someevent', evt => {...});
// генерує події "removeevent" та "removeevent:someevent"
this.off('someevent', evt => {...});
DOM_EVENT::KEY
, де DOM_EVENT - це им'я DOM події, KEY - ключ. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який пов'язаний з KEY.
this.bindNode('x', '.my-div');
this.on('click::x', evt => {
alert('clicked ".my-div"');
});
DOM_EVENT::KEY(SELECTOR)
, де DOM_EVENT - це им'я DOM події, KEY - ключ, SELECTOR - селектор. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який відповідає селектору SELECTOR, і знаходиться в елементі, який пов'язаний з властивістю KEY.
<div class="my-div">
<button class="my-button"></button>
</div>
this.bindNode('x', '.my-div');
this.on('click::x(.my-button)', evt => {
alert('clicked ".my-button"');
});
DOM_EVENT::(SELECTOR)
, де DOM_EVENT - це ім'я DOM події, SELECTOR - селектор. Генерується тоді, коли подія DOM_EVENT спрацьовує на елементі, який відповідає селектору SELECTOR, і знаходиться в пісочниці поточного об'єкта.
this.bindNode('sandbox', '.my-div');
this.on('click::(.my-button)', evt => {
alert('clicked ".my-button"');
});
Те ж саме, що і:
this.bindNode('sandbox', '.my-div');
this.on('click::sandbox(.my-button)', evt => {
alert('clicked ".my-button"');
});
Делеговані події PATH@EVENT
, де PATH - це шлях до об'єкта, події якого ми бажаємо прослуховувати, EVENT - це ім'я події.
this.on('a@someevent', () => {...});
this.on('a.b.c@change:d', () => {...});
При виникненні необхідності слухати зміни в усіх елементах Seemple.Array або у всіх властивостях, що відповідають за дані Seemple.Object, замість імені властивості можна вказати зірочку "*".
this.on('*@someevent', () => {...});
this.on('*.b.*.d@change:e', () => {...});
Різні комбінації
Всі наведені вище варіанти синтаксису можна комбінувати довільним способом.
this.on('x.y.z@click::(.my-selector)', () => {...});
binder: object
binder
(байндер, прів'язчик) містить всю інформацію про те, як синхронізувати значення властивості з прив'язаним до нього DOM елементом. Для всіх методів байндера контекст (this
) - відповідний DOM вузол.
Властивості
Iм'я | Тип | Опис |
---|---|---|
on optional | string function | Ім'я DOM події (або список імен подій, розділених пробілами), після спрацювання якогї витягується стан DOM елемента і встановлюється властивість. Крім цього, значенням властивості може бути функція, яка встановлює обробник довільним чином. |
getValue optional | function | Функція, яка відповідає за те, як витягти стан DOM елемента |
setValue optional | function | Функція, яка відповідає за те, як встановити значення DOM елементу |
initialize optional | function | Функція, яка запускається при ініціалізації прив'язки. Наприклад, може бути використана для ініціалізації jQuery плагіна |
destroy optional | function | Функція, яка викликається під час роботи |
Приклади
const binder = {
on: 'click',
getValue(bindingOptions) {
return this.value;
},
setValue(v, bindingOptions) {
this.value = v;
},
initialize(bindingOptions) {
alert('A binding is initialized');
},
destroy(bindingOptions) {
alert('A binding is destroyed');
}
};
this.bindNode('a', '.my-checkbox', binder);
const binder = {
on(callback, bindingOptions) {
this.onclick = callback;
}
// ...
};
// ...
eventOptions: object
Це звичайний об'єкт, котрий може містити службові прапори або довільні дані, які потраплять в обробник події
Приклади
const eventOptions = { silent: true };
this.a = 1;
this.on('change:a', () => {
alert('a is changed');
});
this.set('a', 2, eventOptions); // no alert
const eventOptions = { f: 'yeah' };
this.a = 1;
this.on('change:a', eventOptions => {
alert(eventOptions.f);
});
this.set('a', 2, eventOptions); // alerts "yeah"
class: function
Клас створений за допомогою синтаксису ECMAScript 2015 або повернений функцією Seemple.Class
Приклади
class MyClass {
method() { ... }
};
const MyClass = Seemple.Class({
method() { ... }
});
node
DOM вузол
Приклади
const node = document.querySelector('.foo');
$nodes
Колекція DOM вузлів. Наприклад, jQuery або NodeList.
Приклади
let $nodes = $('.foo');
$nodes = document.querySelectorAll('.bar');
string
Строка
Приклади
const foo = 'bar';
boolean
Логічний тип
Приклади
const bool = true;
number
Число
Приклади
const num = 42;
object
Об'єкт
Приклади
const obj = {
foo: 'x',
['bar']: 'y'
};
array
Масив
Приклади
const arr = ['foo', undefined, null, () => {}];
function
Функція
Приклади
function comeOnBarbieLetsGoParty() {
alert("I'm a Barbie girl, in a Barbie world");
}
null
null
Приклади
const x = null;
*
Будь-який тип
Приклади
let whatever = 'foo';
whatever = 42;
FAQ
Як працює Seemple.js?
Фреймворк використовує акцессори (accessors) для реалізації двостороннього зв'язування даних і вилову подій зміни властивостей.
Для того щоб зрозуміти, як працює двостороннє зв'язування (зокрема, функція Seemple.bindNode), погляньте на цей код:
function bindNode(object, key, node, binder) {
const value = object[key];
Object.defineProperty(object, key, {
get() {
return value;
},
set(v) {
binder.setValue.call(node, v);
}
});
node.addEventListener(binder.on, () => {
value = binder.getValue.call(node);
});
};
Для спрощення, функція не підтримує зв'язок багато-до-багатьох і інші фічі оригіналу.
Як попередньо відрендерити додаток на сервері?
Можна використовувати Seemple.js на сервері Node.js (потрібна наявність jsdom, точніше, об'єкта window
, доступного глобально) або скористатися абсолютно будь-яким шаблонізатором на будь-якій серверній платформі. Перший варіант підходить для статичної генерації HTML, другий - для сторінок, які генеруються при кожному зверненні користувача.
Завдання клієнтської сторони - відтворити додаток з HTML. Seemple#bindNode витягне стан елемента і привласнить його властивості, а Seemple.Array#restore відновить стан колекції.
Що таке debounce?
У документації часто зустрічається фраза "мікропаттерн debounce". Це поширений патерн, який перетворює кілька викликів функції протягом певного часу в один виклик. Детальніше тут.
Що з себе повинен представляти великий додаток?
Додаток на базі Seemple.js, як правило, представляє з себе один вкладений JavaScript об'єкт, кожна гілка якого - екземпляр Seemple. Нові гілки додатку створюються за допомогою Seemple#instantiate, що гарантує цілісність програми та можливість повернути попередній стан додатку або однієї його гілки звичайними привласненням.
Як відрендерити один об'єкт в контейнерах декількох колекцій?
Перше: потрібно встановити класу цього об'єкту властивість bindRenderedAsSandbox
зі значенням false
. Це відключає автоматичне створення пісочниці при рендеринзі об'єкта в масиві (так як заборонено одному об'єкту мати дві пісочниці).
Друге: за подією render
перевірити, в якій масив був вставлений об'єкт і оголосити байндінги, відповідні до масиву. Батьківський масив і відмальований елемент можна отримати, звернувшись до властивостей parentArray
і node
об'єкта події.
Приклад. Є клас об'єкта User
і дві колекції: UsersA
і UsersB
(їх Seemple.Array#itemRenderer може відрізнятися). Для обох колекцій User
використовується в якості Seemple.Array#Model.
class User extends Seemple.Object {
constructor() {
super();
this.bindRenderedAsSandbox = false;
setInterval(() => {
// змінивши name зміняться і всі пов'язані
// з цією властивістю елементи
this.name = Math.random();
}, 5000);
}
onRender(evt) {
const { parentArray, node } = evt;
if(parentArray instanceof UsersA) {
this.bindNode({
// створюємо псевдо-пісочницю
// для синтаксичного цукру в селекторах
// (це не обов'язково)
nodeA: node,
name: ':bound(nodeA) .name',
email: ':bound(nodeA) .email',
});
} else if(parentArray instanceof UsersB) {
this.bindNode({
nodeB: node,
name: ':bound(nodeB) .user-name',
});
}
}
}
Насправді є багато способів вирішення цієї задачі. Наприклад, можна оголошувати байндінги на рівні масиву (тобто масив буде слухати подію render
вставлених об'єктів) або на рівні масиву прив'язувати тільки псевдо-песоніцу, а на рівні об'єкта слухати подію bind
і оголошувати інші прив'язки...