Як використовувати m.js Компактний код - просте використання

Як використовувати m.js

Як використовувати m.js - m-framework.com

Використання m.js, окрім тривіального асинхронного підключення, має цікаві особливості запуску коду. В m.js вбудовано завантажувач модулів та їх CSS.

Про все по-порядку.

Як підключити m.js з нашого CDN:

...
<script src="https://cdn.m-framework.com/js/1.1.min/m.js" async></script>
</body>

Або з локальної копії, отриманої з GitHub:

...
<script src="/js/m.js" async></script>
</body>

Атрибут `async` в тегах скриптів рекомендований Google PageSpeed Insights для прискорення роботи сторінки. Ми вирішили серйозно підійти  до питання асинхронності і навіть головний скрипт m.js підключаємо асинхронно (не те що деякі всесвітньо-відомі бібліотеки).

Що вміє сам m.js розказано на окремій сторінці.

Як завантажуються модулі і де знаходиться скрипт типу "site.js", "init.js", чи "start.js"? Вони відсутні. І ми пояснимо, чому.

Розглянемо простий приклад з сірою кнопкою прокрутки в правій нижній частині екрану, корту ви вже могли помітити на сторінках даного сайту. Дана кнопка при натисненні на неї прокручує сторінку до верхньої частини, за  це відповідає окремий модуль на кілька рядків коду.

Як ініціюється даний модуль:

<a class="scroll-up"
data-m-action="scroll2"
data-m-context="#top"
data-m-auto-hide="true"></a>

Як бачите, в тегу A є атрибут data-m-action , саме він визначає який модуль буде підключатись. Наступний тег data-m-context містить текстовий селектор для передачі в модуль аргументу, по відношенню до якого можна буде здійснити певні дії. Тобто, m.js асинхронно підключить в тіло сторінки скрипт з під-каталогу /app/ з того ж місця, де лежить m.js, визначить елемент за селектором з data-m-context та викличе функцію модулю з контекстом this у даному випадку елемента A та з аргументом у вигляді попередньо визначеного елементу.

Звучить трохи складно, але давайте поглянемо на код згадуваного простого модулю:

if (typeof m == 'undefined') {
var m = function () {};
m.fn = m.prototype = {};
}
m.fn.scroll2 = function(context) {

if (typeof context == 'undefined' || context === null || !(context instanceof m))
return false;

var
top = this.data.top || 0,
scroll_link = this,
scroll = function() {
var scroll_elem = parseInt(m('document').first.scrollTop) == 0 &&
parseInt(m('body').first.scrollTop) !== 0 ? m('body') : m('document');
scroll_elem.animate({
scrollTop: parseInt(m(context).first.offsetTop) + parseInt(top)
}, 300);
};

if (this.length == 0) {
return scroll();
}

this.on('click', function(e) {
e.preventDefault();
scroll();
});

if (this.attr('data-m-auto-hide') !== null) {
m('window').on('scroll', function (e) {
scroll_link.css({
visibility: parseInt(window.scrollY) <= parseInt(m(context).first.offsetTop) ? 'hidden' : 'visible',
opacity: parseInt(window.scrollY) <= parseInt(m(context).first.offsetTop) ? 0 : 1
});
});

m('window').event_fire('scroll');
}

return true;
};

Спочатку в коді кожного модуля ми перестраховуємось на випадок, якщо m.js досі не завантажено а скрипт модуля було оголошено раніше (асинхронність же) і створюємо порожній об'єкт m.fn функції m. Далі розширюємо набір fn нашим модулем, в котрого всередині контекст this це тег A, в котрому зазначалося data-m-action="scroll2" , та аргумент context за селектором з data-m-context. В коді далі визначається сама функція прокручування, здійснюються маніпуляції стосовно допоміжного атрибута для приховування кнопки та найголовніше - прив'язується подія натиснення на A (тобто this) та виклик функції прокручування. Елемент context використовується для визначення його позиції та прокручування до цієї позиції.

Для полегшення сприйняття, домовимось, що елемент-ініціатор якоїсь події - це елемент з заданим data-m-action а елемент по відношенню до якого будуть здійснюватись дії - це елемент за селектором data-m-context, тому селектор має бути максимально унікальним та вичерпним.

Бувають випадки, коли дія повинна здійснюватись по відношенню до того ж самого елементу-ініціатора. В такому разі, можна просто не вказувати data-m-context, наш m.js передасть аргументом той самий елемент-ініціатор. Це буває досить зручно, наприклад в модулі modal_click і з зображенням в шапці даної статті.

Як ви вже можете здогадуватись, ми наполегливо не рекомендуємо використовувати окремі файли для ініціювання модулів чи функцій. Все, чого достатньо, лиш вказати в атрибуті HTML елементу який модуль повинен з ним працювати.

В нашому JS-фреймворкові є наступна функція, котра, як ви бачите, викликається автоматично:

(function() {
...
m('[data-m-action]').init();
})();

Тобто, по відношенню до кожного елементу з атрибутом-ініціатором data-m-action буде виконано магічну функцію init() зі стеку m.fn. Саме ця функція перевірить чи не було вже підключено в тіло сторінки асинхронний скрипт за назвою модулю, спробує підключити його та відповідний CSS за тією ж назвою, спробує викликати функцію модулю з необхідним контекстом this та аргументом. Такий підхід дозволяє суттєво прискорити завантаження сторінки та дозволяє бути певним, що в документ буде підвантажено тільки необхідні модулі без зайвих витрат трафіку. З використанням nginx та  HTTP/2 доставлення модулів кешується, що суттєво прискорює роботу сайту.

Окремо зазначимо, що один і той самий елемент може бути ініціатором для кількох модулів (їх назви в такому разі слід записати через пробіл). Така складна поведінка використовується досить рідко і ми сподіваємось, що для нескладних задач Вам цілком вистачить готових стандартних модулів.

Ознайомлюйтесь з внутрішніми функціями в m.js та з набором модулів з /app/ , які можна викликати через атрибут data-m-action.

Коментарі користувачів


Вибачте, Ви не можете залишити коментар. Спробуйте авторизуватись за допомогою логіну та паролю або скористайтеся однією з соціальних мереж: