Qu рекомендует три способа организации кода в зависимости от задач:
Все способы регистрируются через Qu.lib() и получают доступ к ядру Qu.
Рекомендуемый префикс для data аттрибутов data-qu-{moduleName}-{attribute}. Стандартные аттрибуты и анимации предусмотрены просто с префиксом data-qu-{attribute}.
data-qu-opening — появление элемента.data-qu-closing — закрытие элемента.data-qu-animation-open="{effect}" — анимация для появления элемента.data-qu-animation-close="{effect}" — анимация для закрытия элемента.data-qu-loading="{true/false}" — анимация для эффекта загрущающегося элемента.[data-qu-animation-open="fade"] { transform: translateY(-20px) scale(0.95); }
[data-qu-animation-open="fade"][data-qu-opening] { transform: translateY(0) scale(1); }
[data-qu-animation-close="fade"][data-qu-closing] { transform: translateY(-20px) scale(0.95); }
// vars можно перезадать к конкретным элементам
.element[data-qu-loading] {
--qu-loading-bg: rgba(255, 255, 255, 0.7);
--qu-loading-color: black;
--qu-loading-size: 32px;
--qu-loading-zindex: 1300000000;
}
Самый простой способ. Подходит для утилит и простых модулей.
/*!
* LibExample_literal (Object Literal version)
* Component for Qu
*
* @package LibExample_literal
* @author Serge Galich
* @copyright 2025
* @license MIT
* @website http://qujs.ru/how-to-create-module/
*
* @requires Qu
*/
Que(() => {
// Пример регистрации модуля через переменную
Qu.lib('LibExample_literal', {
name: 'LibExample_literal',
version: '1.0',
loaded: function(quInstance) {
// Вызывается сразу после регистрации
console.log('Модуль LibExample_literal загружен');
},
init: function(quInstance, params) {
// Инициализация модуля
console.log('Модуль LibExample_literal инициализирован', params);
},
test: function() {
Qu.debug('test');
}
});
// Использование после регистрации
Qu.LibExample_literal.test();
});
Один экземпляр на весь компонент в отдельном файле.
/*!
* LibExample_Singleton (Object version)
* Component for Qu
*
* @package LibExample_Singleton
* @author Serge Galich
* @copyright 2025
* @license MIT
* @website http://qujs.ru/how-to-create-module/
*
* @requires Qu
*/
(function(global) {
'use strict';
const LIB_NAME = 'LibExample_Singleton';
if (global.Qu && global.Qu[LIB_NAME]) {
global.Qu.debug(`⚠️ [${LIB_NAME}] Already registered, skipping duplicate`);
return;
}
var Qu = null;
var Module = {
name: LIB_NAME,
version: '1.0',
_initOnce: false,
_config: {
assets_url: '/assets/',
},
config: function(options) {
Object.assign(this._config, options);
return this;
},
debug: function(...args) {
Qu.debug(...args);
},
use: function (fn) {
if (typeof fn === 'function') {
fn(this, Qu);
}
},
extend: function () {
if (Array.isArray(global[LIB_NAME + 'Extend'])) {
global[LIB_NAME + 'Extend'].forEach((fn) => {
this.use(fn);
});
global[LIB_NAME + 'Extend'] = [];
}
},
loaded: function(quInstance) {
Qu = quInstance;
this.extend();
console.log('ONLOAD LibExample_Singleton')
},
initOnce: function(params = {}) {
if(this._initOnce === true) { return; }
this._initOnce = true;
},
init: function(quInstance, params = {}) {
this.initOnce(params);
this.config(params);
this._init();
},
test: function(wtf) {
Qu.debug(wtf);
},
_init: function() {
console.log(`${LIB_NAME} initialized`);
if (Qu && Qu.Frame) {
Qu.Frame.test('LibExample_Singleton init');
}
},
// Другие методы тоже могут использовать Qu
someMethod: function() {
if (Qu) {
Qu.test('Using Qu from method');
}
}
};
if (global.Qu) {
global.Qu.lib(LIB_NAME, Module);
} else {
global._QuLibs = global._QuLibs || [];
global._QuLibs.push({ name: LIB_NAME, instance: Module });
}
})(typeof window !== 'undefined' ? window : global);
Множество независимых экземпляров.
/*!
* LibExample_class (Object-Class version)
* Component for Qu
*
* @package LibExample_class
* @author Serge Galich
* @copyright 2025
* @license MIT
* @website http://qujs.ru/how-to-create-module/
*
* @requires Qu
*/
(function(global) {
'use strict';
const LIB_NAME = 'LibExample_class';
if (global.Qu && global.Qu[LIB_NAME]) {
global.Qu.debug(`⚠️ [${LIB_NAME}] Already registered, skipping duplicate`);
return;
}
let Qu = null;
function Constructor(params = {}) {
this.id = Date.now() + '_' + Math.random().toString(36).substr(2);
this.version = '1.0';
this.params = params;
console.log(`NEW ${LIB_NAME}`, this.id);
}
Constructor.debug = function(...args) {
Qu.debug(...args);
},
Constructor.use = function (fn) {
if (typeof fn === 'function') {
fn(Constructor, Qu);
}
};
Constructor.extend = function () {
if (Array.isArray(global[LIB_NAME + 'Extend'])) {
global[LIB_NAME + 'Extend'].forEach((fn) => {
Constructor.use(fn);
});
global[LIB_NAME + 'Extend'] = [];
}
};
// ✅ Методы через контейнер
Constructor.loaded = function(quInstance) {
console.log(`${LIB_NAME}.loaded`);
Qu = quInstance;
Constructor.extend();
};
Constructor.sen = function(mes) {
console.log(`${LIB_NAME}: ${mes}`);
};
// функционал экземпляра
Constructor.prototype = {
constructor: Constructor,
tester: function() {
console.log('wtf', Qu, LIB_NAME);
}
};
if (global.Qu) {
global.Qu.lib(LIB_NAME, Constructor);
} else {
global._QuLibs = global._QuLibs || [];
global._QuLibs.push({ name: LIB_NAME, instance: Constructor });
}
})(typeof window !== 'undefined' ? window : global);