Добро пожаловать в QCObjects. Открытая платформа, которая позволяет опытным разработчикам создавать микросервисы и микросерверы в виде многоуровневой архитектуры. С помощью QCObjects можно также писать как для фронтенда, так и для бэкенда, используя общую синтаксическую конструкцию на чистом JavaScript. Это кросс-браузерное, кроссплатформенное и кросс-фрэйм решение.Установите его, создайте поле ввода или реализуйте функциональность навигации домой всего за один шаг.
Это основной справочный документ!
Репозиторий и README доступны по адресу https://qcobjects.dev.
Проверьте официальный сайт QCObjects по адресу https://qcobjects.com.
Этот проект следует Кодексу поведения Contributor Covenant. Участвуя в нем, вы обязаны придерживаться этого кодекса. Неприемлемое поведение можно сообщить по адресу info@quickcorp.cl.
Добровольные вклады приветствуются!
Вы можете внести свой вклад в QCObjects, следуя набору правил, изложенных в файле CONTRIBUTING.md.
Часто некоторые люди путают название QCObjects с CObjects (может быть, когда-нибудь это изменится...), но буква Q имеет важное значение: она означает быстрый! Полное название QCObjects расшифровывается как Быстрые компоненты и объекты, поэтому буквы Q, C, O пишутся заглавными.
Для тех, кто не хочет читать всё это сегодня, вот небольшое видео, которое объясняет, что такое QCObjects и что можно сделать с ним.
js/packages/cl.quickcorp.services.js
]:](#шаг-2-затем-создайте-некоторые-сервисы-наследуя-классы-в-файл-jsppackagesclquickcorpservicesjs-)
Чтобы предотвратить блокировку рендера ресурсами, QCObjects внедрил фабричную функцию Package.
Начиная с версии 2.1.251, QCObjects предоставляет простой способ ленивой загрузки изображений, используя последний стандарт для браузеров.
<img src="img/preloader.svg" lazy-src="img/myrealimage.png"/>
```В приведённом выше коде используется заглушка (лёгкий вес) изображение для первой загрузки, а атрибут **lazy-src** используется для установки реального изображения, которое будет показано после завершения процесса ленивой загрузки. QCObjects загружает все объявленные теги **<img>** внутри компонента в режиме ленивой загрузки, если они имеют атрибут lazy-src, после перестроения или загрузки компонента. Также, QCObjects использует [API Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) (когда доступен), чтобы определить, является ли изображение lazy-src или src визуально полезным для отображения. Эффект ленивой загрузки заметен в первую очередь при первом запуске PWA. При последующих запусках скорость загрузки значительно увеличивается, что затрудняет восприятие глазом человека этих изменений. Однако эта функция существенно влияет на опыт пользователя при низкой скорости интернет-соединения или при работе с очень большими изображениями. Эта функция является частью рекомендованных функций для PWA, представленных на [веб-сайте разработчиков Mozilla](https://developer.mozilla.org/) в статье о прогрессивной загрузке. Вы можете прочитать эту статью [здесь](https://developer.mozilla.org).Если вы не хотите использовать ленивую загрузку для изображений, вы всегда можете продолжать использовать обычный способ загрузки, не добавляя атрибут **lazy-src** к тегу **<img>** и используя традиционный атрибут **src**.# Кроссбраузерный JavaScript-фреймворк для паттернов MVC
----------------------------------------
[QCObjects](https://qcobjects.dev) — это JavaScript-фреймворк, предназначенный для упрощения реализации паттернов MVC в чистом JavaScript. Вам не требуется использование TypeScript или какого-либо транспайлера для запуска [QCObjects](https://qcobjects.dev). Он работает непосредственно в браузере и использует чистый JavaScript без дополнительных зависимостей. Вы можете создавать свои компоненты, выраженные в реальных объектах JavaScript, или расширять нативные объекты DOM для использования по своему усмотрению. Также можно использовать [QCObjects](https://qcobjects.dev) вместе с CSS3-фреймворками, такими как [Foundation](https://foundation.zurb.com), [Bootstrap](https://getbootstrap.com) и мобильными JavaScript-фреймворками, такими как [PhoneGap](https://phonegap.com) и OnsenUI (https://onsen.io).

# Установите его, создайте поле ввода или добавьте функциональность "назад", всего за один шаг.
QCObjects можно установить на вашем компьютере; он приходит со средством командной строки и командами для создания шаблона вашего приложения всего за один шаг. Вернитесь домой без необходимости покидать страницу и создайте затенённое поле ввода всего за один шаг.
# Динамическая архитектура компонентов

[](https://app.fossa.com/projects/git%2Bgithub.com%2FQuickCorp%2FQCObjects?ref=badge_shield)# Спецификация ECMA-262
--------------------------
См. [ECMAScript® Yöntem Dili 2020 Spesifikasyonu](https://tc39.github.io/ecma262/#sec-intro) для справки
# Авторское право
-----------
Авторское право © Жан Макучака и [QuickCorp](https://quickcorp.org) <info@quickcorp.cl>
# Пример
--------------
## Пример PWA
Проверьте живой пример PWA на основе фронтенд-компонента QCObjects здесь:
[PWA QCObjects](https://newapp.qcobjects.dev/)
## Пример с использованием Foundation
Проверьте пример, использующий компоненты Foundation, здесь:
[Пример с использованием Foundation](https://github.com/QuickCorp/quickobjects_sample1foundation)
## Демонстрация интеграции с Materializecss
Просмотрите демонстрацию использования MaterializeCSS здесь:
[Демо с использованием Materializecss](https://qln.link)
## Демонстрация с использованием чистого CSS
Просмотрите демонстрацию использования чистого CSS здесь:
[Демо с использованием чистого CSS](https://github.com/QuickCorp/qcobjects_profile_browser)
## Пример использования QCObjects для манипулирования объектами канваса
Следующий код показывает, как QCObjects могут манипулировать объектами канваса непосредственно и внутри компонентов.
```html
<!DOCTYPE html>
<html>
<head>
<title>Демо</title>
<script type="text/javascript" src="https://cdn.qcobjects.dev/QCObjects.js"></script>
<script type="text/javascript">
var canvas1, canvas2, canvas3, container;
CONFIG.set('relativeImportPath','src/');
/**
* Основное импортирование.
*/
Import('cl.quickcorp', function() {
/**
* Супер контейнер MyOwnBody
*/
Class('MyOwnBody', HTMLBodyElement, {
customAttr: 'custom',
body: document.body // заменяет базовый элемент body
});
```md
# Журнал разработчика
--------------
Официальный [Журнал разработчика QCObjects](https://devblog.qcobjects.org/) размещен на [Hashnode](https://hashnode.com/). Журнал пишется лично Джоном Макучей, автором [QCObjects](https://qcobjects.com), который подробно объясняет лучшие практики и дает лучшие советы и хитрости использования самых продвинутых возможностей QCObjects.
```# Вилка проекта
--------------
Пожалуйста, сделайте вилку этого проекта или создайте ссылку на этот проект в вашем файле `README.md`. Прочтите файл `LICENSE.txt` перед использованием данного кода.
# Станьте спонсором
------------------
Если вы хотите стать спонсором этого замечательного проекта, вы можете сделать это [здесь](https://sponsorsignup.qcobjects.dev/).
# Посмотреть QCObjects SDK
----------------------------
Вы можете просмотреть [QCObjects SDK](https://sdk.qcobjects.dev/) и следовать примерам для создания своих собственных компонентов с уникальными функциями.
# Донат
--------------
Если вам понравился данный код, пожалуйста, [ДЕНОНИРУЙТЕ](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UUTDBUQHCS4PU&source=url)!
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UUTDBUQHCS4PU&source=url)
[](https://www.patreon.com/join/qcobjects?)
# Установка
------------
## Использование QCObjects с Atom:
```shell
> apm install qcobjects-syntax
https://atom.io/packages/qcobjects-syntax
> npm install qcobjects-cli -g && npm install qcobjects --save
## Установка контейнерной среды для Docker:
docker pull -a quickcorp/qcobjects-playground && docker run -it --name qcobjects-playground --rm -it quickcorp/qcobjects-playground
ПРЕДУПРЕЖДЕНИЕ: Выполните это только в свежей/чистой/новой установке Ubuntu 18.x, не делайте этого в существующей производственной среде. Вас попросят предоставить права доступа от имени администратора (sudo
).
curl -L https://cdn.qcobjects.dev/install_qcobjects_ubuntu18x.sh | sh
ПРЕДУПРЕЖДЕНИЕ: Я не несу ответственности за повреждение вашей инфраструктуры при использовании автоматизированного скрипта установки в небезопасной сети. Убедитесь, что все ваши репозитории и скрипты находятся под протоколом HTTPS с действительным сертификатом. Для получения лучших результатов рекомендую вам скачать скрипт, отредактировать его под свои специальные нужды и затем выполнить его на вашем компьютере локально.
curl -L https://cdn.qcobjects.dev/install_qcobjects_rhel8.sh | sh
su -c "curl -L https://cdn.qcobjects.dev/install_qcobjects_raspbian9.sh | sh" root
Тестировалось на macOS Catalina 10.15.3
curl -L https://cdn.qcobjects.dev/install_qcobjects_macOS.sh | zsh
2.- Из командной строки установите qcobjects-cli с помощью npm
npm i qcobjects-cli -g
3.- Создайте директорию для вашего проекта
md mynewproject && cd mynewproject
4.- Создайте новое Progressive Web Application QCObjects
qcobjects create mynewproject --pwa
QCObjects нативно поддерживается самыми известными облачными провайдерами. В большинстве случаев вы можете установить его и настроить всё одним шагом.
Если вы хотите забыть про apt-get
и руководство по конфигурации, просто приступайте к развертыванию вашего проекта с помощью преднастроенной однонажатия приложения, включающей QCObjects CLI, QCObjects SDK и встроенного сервера QCObjects HTTP/2. Разверните его на виртуальной машине Droplet или кластере Kubernetes за 60 секунд или менее.
Создайте свой собственный QCObjects DigitalOcean Droplet здесь
Amazon Machine Image (AMI) предоставляет информацию, необходимую для запуска экземпляра. При запуске экземпляра вам следует указать AMI. Вы можете запустить несколько экземпляров из одного AMI, когда вам нужны несколько экземпляров с одинаковой конфигурацией. Вы также можете использовать различные AMI для запуска экземпляров, если вам нужны экземпляры с различной конфигурацией.AMI включает следующее:
Начните создание своего AMI QCObjects здесь
Частное изображение позволяет вам создать новый AMI, установив программное обеспечение AWS Marketplace на изображение, выбранное из доступных AMI вашего аккаунта AWS. Это позволяет лучше соответствовать внутренним спецификациям безопасности, управления и соответствия требованиям. Как и стандартные AMI AWS Marketplace, каждый частный образ будет включать подписку для установленного продукта и будет иметь счет за использование программного обеспечения через AWS Marketplace.
Начните создание своего частного AMI QCObjects здесь
<script type="text/javascript" src="https://cdn.qcobjects.dev/QCObjects.js"></script>
<script src="https://cdn.jsdelivr.net/npm/qcobjects/QCObjects.min.js"></script>
```## Использование последней не-минифицированной версии из CDN jsDelivr
```html
<script src="https://cdn.jsdelivr.net/npm/qcobjects/QCObjects.js"></script>
<script src="https://unpkg.com/qcobjects@latest/QCObjects.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qcobjects/[VERSIЯ]/QCObjects.js"></script>
Где [VERSIЯ]
— это соответствующая последняя версия с использованием цифровой нотации, пример: чтобы использовать версию 2.1.420:
<script src="https://cdnjs.cloudflare.com/ajax/libs/qcobjects/2.1.420/QCObjects.js"></script>
Вы не обязаны минифицировать QCObjects, но если вы всё же хотите использовать минифицированный код, вы можете сделать это:
<script src="https://cdnjs.cloudflare.com/ajax/libs/qcobjects/2.1.420/QCObjects.min.js"></script>
Ещё раз, замените 2.1.420
на номер желаемой версии.
Здесь представлены основные символы и концепции справочника QCObjects.
Основной тип всех элементов.
С помощью ComplexStorageCache можно управлять кэшем для любого объекта и сохранять его в локальном хранилище.
var cache = new ComplexStorageCache({
index: object.id, // Индекс объекта
load: (cacheController) => {}, // Функция для выполнения при первом обращении
alternate: (cacheController) => {} // Альтернативная функция для выполнения при повторном обращении
});
var dataObject = {
id: 1,
prop1: 1,
prop2: 2
};
```var cache = new ComplexStorageCache({
index: dataObject.id,
load: (cacheController) => {
dataObject = {
id: dataObject.id,
prop1: dataObject.prop1 * 2, // Изменение значения свойства
prop2: dataObject.prop2
};
return dataObject;
},
alternate: (cacheController) => {
dataObject = cacheController.cache.getCached(dataObject.id); // Установка dataObject с кэшированным значением
return;
}
});
// В следующий раз вы сможете получить объект из кэша
var dataObjectCopyFromCache = cache.getCached(dataObject.id);
console.log(dataObjectCopyFromCache); // Будет показывать те же самые значения объекта, что и dataObject
```### asyncLoad
Функция **asyncLoad** загружает код один раз в асинхронном режиме. Это полезно для обеспечения того, чтобы некоторые начальные процессы не повторяли свое выполнение и не загружались после чувствительного кода.
#### Пример использования:
```javascript
asyncLoad(() => {
// мой код здесь
}, args);
// Где args — это массив аргументов, он может быть специальным объектом "arguments"
let doSomething = (arg1, arg2) => {
asyncLoad((arg1, arg2) => {
console.log(arg1);
console.log(arg2);
}, arguments);
};
doSomething(1, 2); // Код функции doSomething будет выполнен один раз после очереди других асинхронных функций и до события готовности страницы.
Это НЕ определение класса ECMAScript 2015 (см. класс ECMAScript 2015 для справки).Класс — это специальная функция, которая помогает вам объявить класс более удобным и совместимым способом. Она работает кроссбраузерно, и я надеюсь, что ECMA когда-нибудь примет что-то подобное. Чтобы избежать путаницы с этим, QCObjects использует "Class", а не "class" (учтите CamelCase).#### Пример использования:
Class('MyClassName', MyClassDefinition);
Где MyClassDefinition — это объект с прототипом QCObjects.
Class('MyClassName', InheritClass, {
propertyName1: 0, // просто для декларации
propertyName2: '',
classMethod1: function() {
// какой-то код здесь
// учтите, что вы можете использовать объект "this"
return this.propertyName1;
},
classMethod2: function() {
// какой-то код здесь
return this.propertyName2;
}
});
var newObject = New(MyClassName, {
propertyName1: 1, // это инициализирует значение в 1
propertyName2: 'some value'
});
console.log(newObject.classMethod1()); // это покажет число 1
console.log(newObject.classMethod2()); // это покажет "some value"
Это специальный метод, встроенный для упрощения работы при динамическом манипулировании DOM. Вы можете вставить даже компонент, объект QCObjects или элемент DOM внутрь другого элемента HTMLElement.
[element].append([object or element]);
// Это создаст класс QCObjects с названием "canvas", расширяющий HTMLCanvasElement с свойством customAttr со значением "custom"
Class('canvas', HTMLCanvasElement, {
customAttr: 'custom'
});
// Это объявляет экземпляр canvas1 от класса canvas
let canvas1 = New(canvas, {
ширина: 100,
высота: 100
});
// Это прикрепляет объект canvas1 к телу документа
document.body.append(canvas1);
Когда вы расширяете класс QCObjects из другого, вы можете использовать метод super для получения экземпляра из основной классовой определенной структуры.#### Пример использования:
_super_('ОсновнойКласс', 'ОсновнойМетод').call(this, параметры)
// где this — текущий экземпляр, а параметры — параметры метода
Class('Сверхкласс', InheritClass, {
свойство1: 0, // просто для декларации цели
свойство2: '',
метод1: function() {
// некоторый код здесь
// обратите внимание, что можно использовать объект "this"
return this.свойство1;
},
});
Class('ИмяМоегоКласса', Сверхкласс, {
свойство1: 0, // просто для декларации цели
свойство2: '',
метод2: function() {
// Следующая строка выполнит метод1 из сверхкласса
// но использует текущий экземпляр ИмяМоегоКласса
return _super_('Сверхкласс', 'метод1').call(this);
}
});
var новыйОбъект = New(ИмяМоегоКласса, {
свойство1: Yöntem1, // это инициализирует значение в 1
свойство2: "некоторое значение"
});
console.log(новыйОбъект.метод2()); // это покажет число 1
Создает экземпляр объекта определенного класса QCObjects.
let objectInstance = New(QCObjectsClassName, свойства);
// где свойства — это единственный объект со значениями свойств
Замечание: В объекте с свойствами вы можете использовать как одиночные значения, так и геттеры, но они будут выполняться один раз.
Class('МойУникальныйКласс', Object);
let objectInstance = New(МойУникальныйКласс, {
prop1: 1,
get случайноечисло() { // этот геттер будет выполнен один раз
return Math.random();
}
});
```console.log(objectInstance.случайноечисло); // покажет случайное число
console.log(objectInstance.prop1); // покажет число 1
Одно общее использование определённого класса QCObjects.
Используйте ClassFactory, чтобы получить экземпляр фабрики объявления класса QCObjects. Вы можете получить либо фабрику класса из пакета, либо из очереди стека классов. Чтобы получить ClassFactory из очереди классов, вы можете просто использовать имя класса непосредственно в коде.
/* Когда вы объявляете MyClass с помощью Class(), он сразу же добавляется в очередь классов,
* и вы можете получить фабрику, используя ClassFactory() или вызывая имя MyClass прямо в коде
*/
Class('MyClass', {
a: 1
});
console.log(MyClass === ClassFactory('MyClass')); // будет показывать true
/* С другой стороны, ClassFactory() окажется полезной, когда вы определяете класс в пакете
*/
Package('org.quickcorp.package1', [
Class('MyClass', {
a: 1
})
]);
console.log(MyClass === ClassFactory('MyClass')); // всё ещё покажет true
// Следующая строка также покажет true
console.log(MyClass === ClassFactory('org.quickcorp.package1.MyClass'));
``````javascript
/* An interesting point is the situation where you declared more than one class with the same name MyClass
* in different packages but with different default property values and even different properties
*/
Package('org.quickcorp.package1', [
Class('MyClass', {
a: 1
})
]);
Package('org.quickcorp.package2', [
Class('MyClass', {
a: 2,
b: 1
})
]);
// The last declaration of MyClass will be the one that survives in the queue of classes,
// so a reference to MyClass in the code will point to this class
console.log(MyClass === ClassFactory('MyClass')); // still shows true
```// В этом случае, как MyClass, определенный в org.quickcorp.package1, не будет таким же,
// как тот, который в org.quickcorp.package2, но MyClass в package2 — последний,
// следующая строка покажет false
console.log(MyClass === ClassFactory('org.quickcorp.package1.MyClass'));
// Следующая строка покажет true
console.log(MyClass === ClassFactory('org.quickcorp.package2.MyClass'));
// Следующая строка покажет false
console.log(ClassFactory('org.quickcorp.package1.MyClass') === ClassFactory('org.quickcorp.package2.MyClass'));
Вышеупомянутые примеры сделаны намеренно, чтобы объяснить и продемонстрировать, как область определения классов в QCObjects защищена и обрабатывается, что отражается в использовании ClassFactory.
Поэтому вам следует использовать ClassFactory, когда требуется полный контроль над областью при расширении классов. Пример
// Когда вы обычно расширяете класс с помощью очереди класса, вы делаете следующее:
Class('МойРасширенныйКласс', МойНаследуемыйКласс, {
расширеннаяПараметр1: 'значение параметра',
расширеннаяПараметр2: 2
});
/* Но чтобы защититься от путаницы ссылками, вы можете убедиться, что МойНаследуемыйКласс
является тем, который вы хотите расширить, объявив его в пакете и затем расширив его
*/
Package('org.quickcorp.мойпакет1', [
Class('МойНаследуемыйКласс', {
источникПараметр: 1
})
]);
```// Далее приведён пример определения MyExtendedClass в другом пакете
// org.quickcorp.package2
// расширяющий MyInheritedClass с использованием ClassFactory для получения класса из исходного пакета
// org.quickcorp.myPackage1
Package('org.quickcorp.мойпакет2',[
Class('MyExtendedClass',ClassFactory('org.quickcorp.мойпакет1.MyInheritedClass'),{
extendedParameter1: 'значение параметра',
extendedParameter2: 2
})
])
// Исправление имени пакета
Package('org.quickcorp.mypackage2',[
Class('MyExtendedClass',ClassFactory('org.quickcorp.mypackage1.MyInheritedClass'),{
extendedParameter1: 'значение параметра',
extendedParameter2: 2
})
])// это выведет число 1 (как наследованное значение параметра sourceProp)
console.log(New(МойРасширенныйКласс).источникПараметр)
С помощью _Crypt можно шифровать сериализуемые объекты с помощью пароля
var _строка = New(_Crypt, {string: 'привет мир', key: 'некий ключ шифрования MD5'});
console.log(_строка._encrypt());
console.log(_строка._decrypt()); // расшифровывает зашифрованную строку до исходной
_Crypt.encrypt('привет мир', '12345678866');
_Crypt.decrypt('nqCelFSiq6Wcpw==', '12345678866');
GLOBAL — это специальный класс QCObjects для доступа к глобальному пространству имён. У него есть методы set
и get
для управления внутренними свойствами GLOBAL.
GLOBAL.set('глобальноеСвойство1', 'некое значение в глобальном пространстве имён');
var глобальноеСвойство1 = GLOBAL.get('глобальноеСвойство1');
CONFIG — это умный класс для управления глобальными настройками вашего приложения. Вы можете получить значения свойств либо из файла config.json
, либо из ранее сохранённых значений с помощью вызова set()
.
CONFIG.set('некоеСвойствоНастроек', 'начальное значение');
get
:var некоеСвойствоНастроек = CONFIG.get('некоеСвойствоНастроек');
config.json
:1.- Для начала следует указать, что вы используете файл config.json
, установив значение "useConfigService"
в true
.CONFIG.set('useConfigService', true); // использование файла config.json для настроек конфигурации
2.- После того как вы установили значение выше, QCObjects
будет знать и искать следующие настройки CONFIG
в файле config.json
в папке basePath
вашего приложения.
config.json
:Существует возможность использовать зашифрованный файл config.json
для защиты ваших настроек от роботов, которые могут украсть незащищенные данные с вашего веб-приложения (например, ключи API).
Чтобы зашифровать ваш JSON-файл, перейдите по адресу https://config.qcobjects.dev, введите домен и содержимое файла config.json
. Инструмент зашифрует ваш JSON, и вы сможете скопировать зашифрованное содержимое для его вставки в файл config.json
. QCObjects
узнает, что данные зашифрованы, и процесс декодирования данных будет прозрачен для вас.
CONFIG
Иногда вам потребуется установить значение из источника, который не является статическим, такого типа как переменные окружения или другой источник динамических данных. Чтобы получить значение с помощью CONFIG
из динамического источника, вам нужно использовать процессор. Есть общие процессоры, заранее определённые, такие как $ENV
(доступен только в CLI, Collab и Node) и $config
(доступен во всех средах).Процессоры вызываются как мета-значение либо в файле config.json, либо в классе CONFIG.
// файл: config.json
{
"domain": "localhost",
"env1": "$ENV(ENV1)",
"customSettings": {
"value1": "$config(domain)"
}
}
let value1 = CONFIG.get("customSettings").value1;
// value1 = "localhost";
let env1 = CONFIG.get("env1");
// env1 = (переменная окружения ENV1)
// устанавливает ключ "api_key" настроек CONFIG на динамический процессор $ENV, который получает значение API_KEY из переменных окружения
CONFIG.set("api_key", "$ENV(API_KEY)");
let api_key = CONFIG.get("api_key");
// api_key будет содержать значение переменной окружения API_KEY системы
// ($ENV процессор возвращает действительное значение только в Node.js, QCObjects CLI и QCObjects Collab движке)
Статический класс, используемый для установки пользовательских процессоров для CONFIG.
Processor.setProcessor(processor);
Где processor — это названная функция, которая принимает аргументы процессора.
У вас есть переменная окружения с именем SERVICE_URL, которая хранит URL сервиса. Вам нужно использовать это значение в ваших конфигурационных настройках в поле serviceURL, но также вам нужно установить настройки host и port используя распарсенное значение этого URL. Чтобы распарсить значение переменной окружения SERVICE_URL по требованию и заполнить соответствующие настройки в вашем файле config.json
, ваш файл config.json
будет выглядеть следующим образом:```json
// файл: config.json
{
"serviceURL": "$ENV(SERVICE_URL)",
"host": "$SERVICE_HOST(SERVICE_URL)",
"port": "$SERVICE_PORT(SERVICE_URL)"
}
Обработчики **$SERVICE_HOST** и **$SERVICE_PORT** еще не существуют. Для их определения следует использовать:
```javascript
// выполните следующий код в вашем файле init.js или перед загрузкой конфигураций
let SERVICE_HOST = function (arg) {
var processorHandler = this; // чтобы сделать этот код всегда рабочим, не используйте стрелочные функции при определении своих функций
let serviceURL = new URL(processorHandler.processors.ENV(arg));
return serviceURL.host;
};
let SERVICE_PORT = function (arg) {
var processorHandler = this; // чтобы сделать этот код всегда рабочим, не используйте стрелочные функции при определении своих функций
let serviceURL = new URL(processorHandler.processors.ENV(arg));
return serviceURL.port;
};
Processor.setProcessor(SERVICE_HOST);
Processor.setProcessor(SERVICE_PORT);
Затем вам нужно установить переменную окружения SERVICE_URL в вашей оболочке
Это применимо только для систем Unix/Linux
export SERVICE_URL="https://example.com:443/path-to-a-resource/"
и ваши настройки будут динамически загружены следующим образом:
{
"serviceURL": "https://example.com:443/path-to-a-resource/",
"host": "example.com",
"port": "443"
}
И вы получите соответствующие значения, используя CONFIG.get(value)
waitUntil — это вспомогательная функция, которую можно использовать в случае проблем с выполнением кода до тех пор, пока условие не станет истинным. Код внутри waitUntil будет выполнен один раз.ОБСЛУЖИВАНИЕ: Это полезно в некоторых случаях, но чрезмерное использование не рекомендуется.
waitUntil(() => {
// код, который будет выполнен после того, как условие станет истинным
}, () => { return condition; });
// где condition — то, что вы хотите ждать
let someVar = 0;
waitUntil(() => {
console.log('someVar есть');
}, () => { return typeof someVar !== 'undefined'; });
// где условие то, что вы хотите ждать
Определяет пакет QCObjects и возвращает его.
Package('packageName', [packageContent]);
Где packageContent
это массив классов QCObjects. Если передается только параметр packageName
, будет получен ранее объявленный контент пакета.
'use strict';
Package('org.quickcorp.main', [
Class('Main', InheritClass, {
propertyName1: 'propertyValue1',
}),
Class('MyCustomClass', InheritClass, {
propertyName2: 'propertyValue2',
}),
]);
let mainPackage = Package('org.quickcorp.main'); // это вернет ранее объявленный контент пакета 'org.quickcorp.main'
// mainPackage[0] будет определением класса Main.
// Это полезно для внутреннего анализа кода
Техника загрузки пакетов в QCObjects основана на промисах и ориентирована на области видимости. Вы можете проверить загружены ли пакеты, вызывая функцию Package()
с аргументом имени пакета.
Импортирует пакет из другого файла JavaScript#### Использование:
Import(packagename,[ready],[external]);
Где packagename
— имя пакета, ready
— функция, которая будет выполнена после загрузки пакета, а external
— логическое значение, которое указывает, находится ли JS-файл в одной области или является внешним ресурсом.#### Пример (1):
Import('org.quickcorp.main');
Вышеуказанный код попытается импортировать файл JavaScript с названием 'org.quickcorp.main.js' из пути, указанного в значении настройки relativeImportPath
вашего конфигурационного файла CONFIG. Внутри файла JavaScript вам следует объявить пакет, используя Package('org.quickcorp.main',[Class1, Class2...])
.
Import('org.quickcorp.main', function() {
console.log('внешний импорт загружен');
}, true);
Вышеуказанный код теперь пытается загрузить тот же пакет, но использует внешний путь, определенный в настройках remoteImportsPath
вашего конфигурационного файла CONFIG.
Замечание: В обоих вышеуказанных примерах расширение .js
не используется или не специфицировано. Оно используется по умолчанию и не может быть изменено по причинам безопасности.
Установите символ (переменную или функцию) в глобальном пространстве имён.
Export('имя_символа');
(() => {
// это локальное пространство имён
let someFunction = (someLocalParam) => {
console.log(someLocalParam);
};
Export(someFunction); // теперь someFunction находится в глобальном пространстве имён.
})();
// это глобальное пространство имён
someFunction('это работает');
Используйте метод Cast
любого элемента DOM для получения свойств другого типа объекта. Это полезно для преобразования одного типа объекта в другой, что обеспечивает большую гибкость в вашем коде.#### Пример использования:
let resultObject = [элемент или тип QCObjects].cast(объектДляПреобразования);
Где объектДляПреобразования
— это объект, из которого будут взяты свойства и помещены в возвращаемый объект resultObject
методом cast
.
класс('МойСвойКласс', {
prop1: '1',
prop2: 2
});
let obj = document.createElement('div').cast(МойСвойКласс);
Вышеуказанный код создаёт объект DOM и преобразует его в МойСвойКласс
. Поскольку МойСвойКласс
является классом типа QCObjects
, obj
будет иметь свойства prop1
и prop2
, а также станет экземпляром объекта QCObjects
с телом, представляющим собой элемент div
.
Функция тег
полезна для выбора любых элементов DOM с помощью селекторов. тег
всегда возвращает список элементов, который можно отображать, сортировать и фильтровать как любой другой список.
var listOfElements = тег(селектор);
Где селектор
— это селектор запроса DOM.
<!DOCTYPE html>
<html>
<head>
<title>Демо</title>
<script type="text/javascript" src="https://cdn.qcobjects.dev/QCObjects.js"></script>
</head>
<body>
<div class="мойселектор">
<p>Здравствуй мир</p>
</div>
<script>
готово(()=>{
тег('.мойселектор > p').map((element)=>{
element.innerHTML = 'Здравствуй мир! Как дела?';
});
});
</script>
</body>
</html>
```В вышестоящем коде был создан параграф внутри div с CSS-классом "my-selector", затем он был динамически изменён с использованием функции Tag библиотеки QCObjects. Если вы знакомы с фреймворками для работы со селекторами, такими как jQuery, вам понравится эта функциональность.### Готово
Назначьте функцию выполнения после завершения всех действий QCObjects и события `window.onload`. Используйте её для предотвращения ошибок "неопределенного" объекта DOM.#### Пример использования:
```javascript
Ready(() => {
// Ваш код инициализации здесь!
});
Обратите внимание, что если вы определяете динамические компоненты с помощью HTML-тега "component"
, загрузка динамического содержимого не будет триггерить события Ready
. Чтобы поймать код каждый раз, когда загружается динамический компонент, используйте метод завершения контроллера вместо этого.
Вы будете использовать реализацию Ready
в основном тогда, когда хотите внедрять объекты QCObjects вместе с другим фреймворком, который требует это.
Тип класса для компонентов в QCObjects.
[Компонент].domain Возвращает строку с доменом вашего приложения. Это автоматически устанавливается QCObjects во время загрузки.
[Компонент].basePath Возвращает строку с базовым путём URL вашего приложения. Это автоматически устанавливается QCObjects во время загрузки.
ЗАМЕЧАНИЕ: Если вы хотите изменить базовый путь компонента, вам следует использовать _CONFIG.set('componentsBasePath', 'новый путь относительно домена')
в вашем коде инициализации.[Компонент].templateURI
Это строка, представляющая URI шаблона компонента относительно домена. Когда это свойство установлено, компонент будет загружать шаблон и добавлять внутренний контент как часть DOM. Для установки этого свойства рекомендуется использовать функцию помощника ComponentURI.[Компонент].tplsource
Это строка, представляющая источник загрузки шаблона. Может быть "default" или "none". Значение "default" говорит QCObjects загружать шаблон из содержимого templateURI. Значение "none" говорит QCObjects не загружать шаблон откуда бы то ни было.
[Компонент].url Это строка, представляющая полный URL компонента. Это автоматически устанавливается QCObjects при создании компонента.
[Компонент].name
Это строка, представляющая имя компонента. Имя компонента может быть любым алфавитно-цифровым значением, которое идентифицирует тип компонента. Оно используется внутри системы ComponentURI для создания нормализованного URI шаблона компонента.[Component].method
Это строка, представляющая HTTP или HTTPS метод. По умолчанию, каждый компонент устанавливается для использования метода "GET". В большинстве случаев, вам не потребуется менять это свойство.[Component].data
Это объект, представляющий данные компонента. При загрузке шаблона QCObjects получает каждое свойство объекта данных и связывает его с меткой шаблона, которая представляет то же свойство внутри содержимого шаблона между двойными фигурными скобками (например: {{prop1}} в содержимом шаблона будет представлять data.prop1 в экземпляре компонента).
ЗАМЕЧАНИЕ: Для обновления привязок данных требуется перестроить компонент (см. использование метода [Component].rebuild() для получения более подробной информации).[Component].reload
Это булево значение, которое указывает QCObjects, когда следует принудительно перезагружать содержимое компонента из шаблона или нет. Если его значение равно true
, то содержимое шаблона заменит текущие дочерние элементы DOM тела компонента. Если значение равно false
, то содержимое шаблона будет добавлено после последнего дочернего элемента тела компонента.[Component].caching
This boolean value indicates to QCObjects whether caching of the given component is required or not. When a component is cached, the content loaded from the templateURI
is loaded only once. You can set this property as a static class property for setting the default value for each subsequent instance of the component, or you can set an individual value for this property in each component definition. In a world where performance is paramount, the need to provide greater flexibility in caching behavior becomes more relevant than ever.
[Component].routing_mode
Returns a string representation of the routing mode. Its value can be "hash"
, "pathname"
, or "search"
.
NOTE: To change the routing mode for all components, it is recommended to use CONFIG.set('routingMode', 'valid routing mode value')
in your initial code.
[Component].allowed_routing_modes Returns a list representing the valid routing modes. QCObjects uses this list internally for validating the correctness of the routing mode used when building component routes.[Component].routing_nodes Возвращает объект NodeList, представляющий список узлов, загруженных построителем маршрутизации компонента.[Component].routes Возвращает список маршрутов компонента, построенных при создании экземпляра компонента.
[Component].routePath Возвращает строковое представление текущего маршрута.
[Component].selectedRoute Возвращает объект, представляющий текущий маршрут компонента.
[Component].subcomponents Возвращает список компонентов, являющихся дочерними для данного экземпляра компонента.
[Component].body Это элемент DOM, представляющий тело компонента. ЗАМЕЧАНИЕ: Каждый раз, когда тело компонента устанавливается, это вызывает построитель маршрутизации для данного компонента.
[Component].set('property', value) Устанавливает значение для свойства компонента.
[Component].get('property') Возвращает значение свойства компонента.
[Component].rebuild() Перестраивает компонент. Это заставляет вызвать компонентLoader для данного компонента, если это необходимо.
[Component].cast(className or componentClassName) Возвращает преобразование определения компонента в другое. Это полезно для динамического объединения определений компонентов.
[Component].route() Принудительно заставляет конструктор маршрутов компонента перезагрузить маршруты компонента. Это приведёт к вызову перестроения при необходимости.[Компонент].fullscreen() Переводит компонент в полноэкранный режим.
[Компонент].closeFullscreen() Закрывает полноэкранный режим.
[Компонент].css(css объект) Устанавливает CSS свойства для компонента.
[Компонент].append(компонент или QCObjects объект) Добавляет компонент как потомка текущего компонента.
[Компонент].attachIn(селектор) Прикрепляет текущий компонент к любому элементу указанного селектора.
Это представление HTML-тега экземпляра компонента. Каждое объявление тега <component></component>
создаёт связанный экземпляр компонента QCObjects. Хотя сам тег <component>
не является экземпляром, вы можете даже определять некоторые свойства экземпляров, установив соответствующие атрибуты тега, когда они доступны.
Ниже представлен список доступных атрибутов для тега компонента
<component name>
Устанавливает имя связанного экземпляра компонента, созданного QCObjects.
<component name="name_of_component"></component>
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Демо</title>
<script type="text/javascript" src="https://cdn.qcobjects.dev/QCObjects.js"></script>
</head>
<body>
<!-- это загрузит содержимое файла ./templates/main[.tplextension] -->
<component name="main"></component>
</body>
</html>
<component cached>
Устанавливает свойство кеша для связанного экземпляра компонента.ЗАМЕЧАНИЕ: Только значение "true"
может быть установлено, чтобы сообщить QCObjects, что содержимое шаблона компонента должно быть закешировано. Любое другое значение будет истолковано как "false"
.
<component name="name_of_component" cached="true"></component>
<component data-property1 data-property2 ...>
Устанавливает статическое значение свойства для объекта данных в экземпляре компонента. ЗАМЕЧАНИЕ: Объявление свойства данных было создано с целью предоставить простой способ имитации динамического компонента с привязками шаблона. Не используйте его, полагая, что это двустороннее связывание данных. Хотя вы можете получить поведение двустороннего связывания данных, обращаясь к объекту данных из экземпляра компонента, это не то же самое для тега компонента. Объявление свойства данных в тегах компонентов является односторонним связыванием данных из-за архитектуры дерева компонентов.
controllerClass
<component controllerClass>
Определяет пользовательский класс контроллера для экземпляра компонента
<component name="name_of_component" controllerClass="ControllerClassName"></component>
viewClass
<component viewClass>
Определяет пользовательский класс представления для экземпляра компонента
<component name="name_of_component" viewClass="ViewClassName"></component>
```##### Атрибут componentClass
**`<component componentClass>`**
Определяет пользовательский класс компонента для экземпляра компонента
###### Пример использования:
```html
<component name="name_of_component" componentClass="ComponentClassName"></component>
<component effectClass>
Определяет пользовательский класс эффекта для экземпляра компонента
<component name="name_of_component" effectClass="EffectClassName"></component>
<component template-source>
Устанавливает свойство tplsource
связанного экземпляра компонента. Возможные значения — "none"
или "default"
.
<component name="name_of_component" template-source="none"></component>
<component tplextension>
Устанавливает свойство tplextension
связанного экземпляра компонента. Возможные значения — любое расширение файла. Значение по умолчанию — "html"
<component name="name_of_component" tplextension="tpl.html"></component>
Помощник для определения templateURI
компонента в нормализованном виде.
var templateURI = ComponentURI({
'COMPONENTS_BASE_PATH': CONFIG.get('componentsBasePath'),
'COMPONENT_NAME': 'main',
'TPLEXTENSION': "tpl.html",
'TPL_SOURCE': "default"
});
console.log(templateURI); // это будет показывать что-то вроде "templates/components/main.tpl.html", в зависимости от ваших CONFIG настроек
```#### componentLoader
Загружает экземпляр компонента на низком уровне и добавляет содержимое шаблона компонента в тело компонента. В большинстве случаев вам не потребуется вызывать `componentLoader`, чтобы загрузить компонент. Это автоматически вызывается QCObjects, когда это необходимо. `componentLoader` возвращает промис, который срабатывает при успешной загрузке компонента и отклоняется при неудачной загрузке.##### Пример использования:
```javascript
[Promise] componentLoader(componentInstance, load_async)
Где componentInstance
— это экземпляр компонента, созданный методом _New(ComponentDefinitionClass)_
.
componentLoader(componentInstance, load_async).then(
(successStandardResponse) => {
// загрузка компонента выполнена успешно
var request = successStandardResponse.request;
var component = successStandardResponse.component;
},
(failStandardResponse) => {
// загрузка компонента не удалась
var component = failStandardResponse.component;
}
);
Перестраивает каждый компонент, являющийся дочерним элементом элемента DOM, которому принадлежит данный метод. В большинстве случаев вам не потребуется вызывать buildComponents
, чтобы построить или перестроить все компоненты в DOM. Это автоматически вызывается QCObjects, когда это необходимо.
[element].buildComponents()
document.buildComponents()
Встроенный тип класса QCObjects для определения контроллера
Встроенный тип представления QCObjects для определения представления
Встроенный тип класса QCObjects для определения объекта значения
Тип класса QCObjects для сервисов.
[Сервис].домен Возвращает строку с доменом вашего приложения. Устанавливается автоматически QCObjects при запуске.
[Сервис].базовыйПуть Возвращает строку с базовым путём URL вашего приложения. Устанавливается автоматически QCObjects при запуске.[Сервис].url Это строка, представляющая полный URL сервиса. Она может быть абсолютной или относительной к базовому пути, если применимо. Также она может быть внешним URL.
ЗАМЕЧАНИЕ: Для загрузки сервиса внешнего ресурса вам необходимо указать параметр внешний как true при использовании serviceLoader
.
Строка, представляющая имя компонента. Имя сервиса может быть любой алфавитно-цифровой последовательностью, которая идентифицирует экземпляр сервиса. Это не уникальный идентификатор, а просто описательное имя.
**[Сервис].метод**
Строка, представляющая HTTP или HTTPS метод. Возможные значения включают: "GET", "POST", "PUT" и так далее — любое другое значение, которое принимается вызовами REST сервисов.
**[Сервис].data**
Объект, представляющий данные сервиса. Когда QCObjects загружает сервис, он получает ответ и интерпретирует его как шаблон. Поэтому после получения ответа от сервиса каждое свойство объекта данных будет связано с меткой шаблона, представляющей то же свойство внутри содержимого шаблона между двойными фигурными скобками (например, {{prop1}} в контенте шаблона будет представлять собой data.prop1 в экземпляре сервиса).
```**[Service].cached**
Логическое значение, указывающее, требуется ли кэширование ответа сервиса или нет. Когда сервис кэшируется, содержимое шаблона, загруженное с помощью URL сервиса, загружается только один раз. Вам следует установить это значение как false для каждого экземпляра сервиса, чтобы гарантировать, что сервис загружается из ресурса, а не из кэша.#### Методы
**[Service].set('prop', value)**
Устанавливает значение для свойства сервиса.
**[Service].get('prop')**
Возвращает значение свойства сервиса.
### serviceLoader
Загружает экземпляр сервиса и возвращает промис, который выполняется при успешной загрузке ответа сервиса и отклоняется при неудачной загрузке ответа.
#### Пример использования:
```javascript
[Promise] serviceLoader(serviceInstance)
Class('MyTestService', Service, {
name: 'myservice',
external: true,
cached: false,
method: 'GET',
headers: {'Content-Type': 'application/json'},
url: 'https://api.github.com/orgs/QuickCorp/repos',
withCredentials: false,
_new_: () => {
// сервис создан
},
done: () => {
// сервис загружен
}
});
var service = serviceLoader(New(MyTestService, {
data: {param1: 1}
})).then(
(successfulResponse) => {
// Это выведет ответ сервиса как обычный текст
console.log(successfulResponse.service.template);
},
(failedResponse) => {
}
);
Предопределенное определение класса для JSON сервиса
[JSONService].domain Возвращает строку с доменом вашего приложения. Устанавливается автоматически при загрузке QCObjects.
[JSONService].basePath Возвращает строку с базовым путем URL вашего приложения. Устанавливается автоматически при загрузке QCObjects.
[JSONService].url Строковое представление полного URL сервиса. Может быть абсолютным или относительным к basePath, если применимо. Также может быть внешним URL.
ЗАМЕЧАНИЕ: Для загрузки сервиса внешнего ресурса вам нужно указать параметр external в значение true при использовании serviceLoader.[JSONService].name Строковое представление имени компонента. Имя сервиса может быть любым алфавитно-цифровым значением, которое идентифицирует экземпляр сервиса. Это не уникальный идентификатор, а просто описательное имя.
[JSONService].method Строковое представление метода HTTP или HTTPS. Возможные значения: "GET", "POST", "PUT", ... любой другой, который принимает вызовы REST сервисов.
[JSONService].data Объект, представляющий данные сервиса. Когда QCObjects загружает сервис, он получает ответ и интерпретирует его как шаблон. Поэтому после получения ответа от сервиса каждое свойство объекта данных будет связано с меткой шаблона, представляющей то же свойство внутри содержимого шаблона между двойными фигурными скобками (например: {{prop1}} в содержимом шаблона будет представлять data.prop1 в экземпляре сервиса).
[JSONService].cached Логическое значение, которое сообщает QCObjects, требуется ли кэширование ответа сервиса или нет. При кэшировании контента шаблона, загруженного с URL сервиса, он загружается только один раз. Вам следует установить это значение в false для каждого экземпляра сервиса, чтобы гарантировать, что сервис загружается из ресурса, а не из кэша хранения.
[JSONService].set('prop', value) Устанавливает значение для свойства сервиса.[JSONService].get('prop') Возвращает значение свойства сервиса.#### Пример:
Class('MyTestJSONService', JSONService, {
name: 'myJSONservice',
external: true,
cached: false,
method: 'GET',
withCredentials: false,
url: 'https://api.github.com/orgs/QuickCorp/repos',
_new_: function () {
// сервис создан
delete this.headers.charset; // не отправлять заголовок charset
},
done: function (result) {
_super_('JSONService', 'done').call(this, result);
}
});
var service = serviceLoader(New(MyTestJSONService, {
data: { param1: 1 }
})).then(
(successfulResponse) => {
// Это покажет ответ сервиса в виде объекта JSON
console.log(successfulResponse.service.JSONresponse);
},
(failedResponse) => {}
);
```### Класс ConfigService
Загружает конфигурационные настройки из файла `config.json`.
#### Пример:
```javascript
// Устанавливаем относительный путь до файла config.json
ConfigService.configFileName = 'config.json'; // это делается по умолчанию
CONFIG.set('useConfigService', true); // использование config.json для настроек
Статический класс для загрузки внешних зависимостей JavaScript. Часто используется для загрузки библиотек, которые находятся вне пакетной системы QCObjects.
Class("MyNewController", Controller, {
_new_: function () {
var controller = this;
controller.dependencies.push(
New(SourceJS, {
external: false,
url: 'doc/js/my-js-resource.js',
done: function () {
logger.debug("Зависимость загружена");
}
})
);
}
});
Статический класс для загрузки внешнего ресурса CSS.
Class("MyNewController", Controller, {
dependencies: [],
done: function () {
this.dependencies.push(New(SourceCSS, {
external: false,
url: CONFIG.get('basePath') + 'css/my-css-resource.css'
}));
}
});
Суперкласс для определения пользовательских эффектов.
Class('CustomFade', Effect, {
duration: 500, // миллисекунды длительности
apply: function () {
// Вы должны использовать следующую строку для применения эффекта затухания в реальном времени
_super_('Fade', 'apply').apply(this, arguments);
}
});
Особая реализация метода requestAnimationFrame
для эмуляции создания экземпляров потока, что позволяет эффективнее управлять параллельным выполнением задач в реальном времени.ПРИМЕЧАНИЕ: Поскольку этот метод зависит от наличия requestAnimationFrame
, он работает только в современных браузерах.
Timer.thread({
duration:300, // длительность в миллисекундах
timing(timeFraction, elapsed){
return timeFraction; // вы можете изменить эту строку, чтобы вернуть пользовательскую математическую функцию для временной шкалы
},
intervalInterceptor(progress){
if (progress >= 100){
// делайте то, что вам нужно здесь
}
}
});
Класс для управления списками
let myVar = New(ArrayList, [1, 2, 3]);
Расширенное определение для продвинутого управления коллекциями
let collection = New(ArrayCollection, { source: [0, 1, 2] });
Фильтрует массив или объект типа ArrayList, чтобы получить только уникальные элементы. ЗАМЕЧАНИЕ: Он фильтрует только последовательность одного значения.
let myUniqueList = [0, 1, 2, 1, 2].unique();
// будет иметь вид: myUniqueList = [0, 1, 2]
Это предназначено только для использования в скриптах командной строки. Отображает таблицу значений списка.
['a', 'b', 'c', 'd'].table();
// это покажет
┌─────────┬───────┐
│ (index) │ Value │
├─────────┼───────┤
│ 0 │ 'a' │
│ 1 │ 'b' │
│ 2 │ 'c' │
│ 3 │ 'd' │
└─────────┴───────┘
let my_sorted_array = [3,3,4,0,2,1].sort();
// my_sorted_array = [ 0, 1, 2, 3, 3, 4 ];
let my_sorted_list = New(ArrayList, { source: [3,3,4,0,2,1] }).source.sort();
// my_sorted_list = [ 0, 1, 2, 3, 3, 4 ];
Сортирует список объектов по значению свойства.
let my_ordered_list = [
{"b":1,"a":2},
{"b":2,"a":1},
{"b":3,"a":3}
].sortBy("a");
// это приведёт к следующему результату
[
{ b: 2, a: 1 },
{ b: 1, a: 2 },
{ b: 3, a: 3 }
];
Генерирует матрицу в одном измерения.
[].matrix (длина, [значение]) Где длина — количество элементов, а необязательный значение — значение каждого элемента, может быть любым типом данных.
let matrix = Array.matrix(10);
// matrix = [
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
];
let matrix = ArrayList.matrix(10, 1);
// matrix = [
1, 1, 1, 1, 1,
1, 1, 1, 1, 1
];
let a = 1, b = 2;
let c = ArrayList.matrix(10, { a, b });
// c = [
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 },
{ a: 1, b: 2 }
];
Создает двумерную матрицу.
let matrix2d = ArrayList.matrix2d(2, 1);
// [ [ 1, 1 ], [ 1, 1 ] ]
Создает трехмерную матрицу.
let matrix3d = ArrayList.matrix3d(3, "a");
// это приведет к созданию 3x3 матрицы со значением "a" в каждом элементе
[
[ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ],
[ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ],
[ [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ], [ 'a', 'a', 'a' ] ]
];
range(длина)
или range(начальный_индекс, конечный_индекс)
range()
без параметров вернёт пустой список
range(0)
вернёт список с одним элементом со значением 0
logger.debugEnabled=true;
for (var i in range(10)){
(!isNaN(i) && logger.debug(i))
}
// вышеуказанный код покажет
[DEBUG] 0
[DEBUG] 1
[DEBUG] 2
[DEBUG] 3
[DEBUG] 4
[DEBUG] 5
[DEBUG] 6
[DEBUG] 7
[DEBUG] 8
[DEBUG] 9
logger.debugEnabled=true;
// тот же результат будет получен при итерации через диапазон первым
for (var i in {...range(10)}){
logger.debug(i)
}
// вышеуказанный код покажет
[DEBUG] 0
[DEBUG] 1
[DEBUG] 2
[DEBUG] 3
[DEBUG] 4
[DEBUG] 5
[DEBUG] 6
[DEBUG] 7
[DEBUG] 8
[DEBUG] 9
// немного короче синтаксис для того же результата
range(10).map(n => logger.debug(n))
let normalizedMatrix = ArrayList.matrix(3, range(2));
// normalizedMatrix = [ [ 0, 1, 2 ], [ 0, 1, 2 ], [ 0, 1, 2 ] ]
let my3dmatrix = ArrayList.matrix3d(3, range(0, 1));
// my3dmatrix будет
[
[
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ]
],
[
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ]
],
[
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ],
[ [ 0, 1 ], [ 0, 1 ], [ 0, 1 ] ]
]
]
Вычисляет сумму элементов массива.
let s = [1, 2, 3].sum();
// s = 6
Вычисляет среднее значение элементов массива.
let average = [10, 5].avg();
// average = 7.5
```### Array.min
Возвращает минимальное значение из элементов массива.
```javascript
let minValue = [1,2,3].min();
// minValue = 1
Возвращает максимальное значение из элементов массива.
let maxValue = [1,2,3].max();
// maxValue = 3
Класс ShadowedComponent предназначен для создания компонента с использованием Shadow DOM браузера. Узнайте больше о Shadowed Components в этой статье на Hackernoon.
<component componentClass="ShadowedComponent"></component>
Класс FormField предназначен для внедрения поведения формы в ваши компоненты QCObjects. Он имеет обратную связь данных для обнаружения значений полей формы внутри вашего компонента и привязки этих значений к данным вашего компонента. Таким образом, вы не теряете производительность, используя старый метод двухсторонней привязки данных на основе наблюдаемых значений. Для реализации этого продвинутого поведения вам следует выполнить следующие шаги:
Назначьте атрибут data-field к тегу DOM внутри тела компонента, указав соответствующее имя поля в объекте данных.
Назначьте FormField в атрибуте componentClass вашего компонента.3. Чтобы получить данные формы внутри вашего компонента, просто используйте объект componentInstance.data
. Каждое свойство объекта componentInstance.data
будет связано событиями привязки данных со значениями каждого поля формы, имеющего назначенное значение data-field
.##### Пример использования:
<!-- Где вы размещаете компонент -->
<component name="myform" componentClass="FormField"></component>
<!-- шаблон: myform.tpl.html -->
<label for="email"><b>Email</b></label>
<input data-field="email" type="email" placeholder="Введите Email" name="email" required>
<label for="psw"><b>Пароль</b></label>
<input data-field="name" type="text" placeholder="Введите Ваше Имя" name="name" required>
Атрибут data-field="name" будет связан с this.data.name внутри класса компонента и будет обновлен каждый раз, когда происходит событие привязки данных. То же самое относится к data-field="email" и так далее.
Метод executeBindings компонента FormField найдет значения атрибута data-field и сопоставит их с соответствующими полями data в экземпляре компонента.
Внутри тела вашего компонента, когда это компонент FormField, каждый раз, когда DOM отправляет событие "change", вызывается метод executeBindings вашего компонента.
Внутри тела вашего компонента, когда это компонент FormField, каждый раз, когда DOM отправляет событие "blur", вызывается метод executeBindings вашего компонента.
Внутри тела вашего компонента, когда это компонент FormField, каждый раз, когда DOM отправляет событие "focus", вызывается метод executeBindings вашего компонента.
ButtonField является подклассом FormField, который обычно используется для выполнения аналогичных задач, как и FormField. Основное различие между ButtonField и FormField заключается в том, что ButtonField имеет элемент DOM <button>
в качестве тела компонента по умолчанию. В то время как FormField не имеет заранее определенного тела.
<component name="name_of_component" componentClass="ButtonField"></component>
InputField является подклассом FormField, который обычно используется для выполнения аналогичных задач, как и FormField. Основное различие между InputField и FormField заключается в том, что InputField имеет элемент DOM в качестве тела компонента по умолчанию. В то время как FormField не имеет заранее определенного тела.
<component name="name_of_component" componentClass="InputField"></component>
TextField является подклассом FormField, который обычно используется для выполнения аналогичных задач, как и FormField. Основное различие между TextField и FormField заключается в том, что TextField имеет элемент DOM <textarea>
в качестве тела компонента по умолчанию. В то время как FormField не имеет заранее определенного тела.
<component name="name_of_component" componentClass="TextField"></component>
<input>
в качестве своего содержимого по умолчанию. В то время как FormField не имеет заранее определённого содержимого.##### Пример использования:<component name="name_of_component" componentClass="EmailField"></component>
GridComponent имеет заранее назначенное имя со значением "grid". Поэтому будьте внимательны при использовании этого типа компонентов. Также GridComponent предназначен для использования вместе с GridController для расширения его поведения до CSS Grid.
<component componentClass="GridComponent" ...></component>
<component rows="2" cols="2" componentClass="GridComponent" controllerClass="GridController">
<!-- рекомендуется использовать подкомпоненты в качестве элементов сетки -->
<component name="name_of_subcomponent1"></component>
<component name="name_of_subcomponent2"></component>
<component name="name_of_subcomponent3"></component>
<component name="name_of_subcomponent4"></component>
</controller>
Приведённый выше пример создаёт CSS-сетку с двумя столбцами и двумя строками и помещает подкомпоненты внутрь неё.
Не забудьте этот файл:
<!-- файл: grid.tpl.html, вы можете использовать шаблон сетки либо для отображения самой сетки, либо для отображения информации о загрузке -->
<p>Загрузка сетки...</p>
Этот компонент используется для внедрения необходимых DOM-элементов Swagger UI для работы с API Swagger UI. Подробнее читайте в статье блога разработчиков QCObjects под названием Работа с Swagger UI как с компонентом QCObjects.##### Пример использования:
<component componentClass="SwaggerUIComponent" controllerClass="SwaggerUIController"></component>
org.quickcorp.components.splashscreen.VideoSplashScreenComponent
Сильное определение компонента для возможности создания впечатляющего видео-экрана запуска для вашего прогрессивного веб-приложения.
<!-- Добавьте тег компонента экрана запуска как первый компонент в вашем HTML документе -->
<component componentClass="VideoSplashScreenComponent"
data-background="./img/splash/splashscreen-aqua.png"
data-video_mp4="./img/splash/splashscreen-aqua.mp4"
data-video_webm="./img/splash/splashscreen-aqua.webm"
data-video_ogg="./img/splash/splashscreen-aqua.ogv" duration="5000">
<img slot="logo" alt="Логотип" src="./img/logo-qcobjects-white.svg"/>
</component>
<!-- Затем вы можете поместить основной компонент так же, как обычно -->
<component name="main" cached=true controllerClass="MainController">
</component>
org.quickcorp.controllers.GridController
Класс GridController предназначен для использования вместе с компонентом GridComponent, чтобы позволить вам создать сетку CSS для размещения подкомпонентов. Подробнее в org.quickcorp.components.GridComponent.
org.quickcorp.controllers.DataGridController
Класс DataGridController будет использовать данные вашего компонента для отображения множества подкомпонентов. Это часто используется для отображения динамического списка компонентов. Он использует значение атрибута subcomponentClass
в теге компонента для определения того, какой шаблон компонента использовать для построения каждого подкомпонента. Данные каждого подкомпонента будут заполнены значением элемента, связанного с этим подкомпонентом.##### Использование:<component name="name_of_component" controllerClass="DataGridController" subcomponentClass="SubComponentClass">
</component>
Предположим, что вам нужно отобразить список профилей. Каждый профиль имеет фотографию профиля, имя и электронную почту. Вы хотите использовать карточку для представления каждого профиля в списке.
Поэтому вы определяете компонент CardComponent для отображения фотографии, имени и электронной почты элемента в списке.
Class("CardComponent", Component, {
name: "card", // это будет указывать на templates/components/card.tpl.html
data: { // значение этого объекта будет перезаписываться контроллером DataGridController
name: "<имя контакта>",
email: "email@example.com",
profilePicture: "img/photo.png"
}
})
<!-- шаблон: card.tpl.html -->
<img src="{{profilePicture}}" />
<h3>{{name}}</h3>
<p>{{email}}</p>
Затем вам нужно поместить компонент для генерации списка карточек.
<component name="loading_list" componentClass="MyListComponent" controllerClass="DataGridController"
subcomponentClass="CardComponent">
</component>
<!-- шаблон: loading_list.tpl.html -->
<p>Загрузка списка...</p>
Последним шагом является определение MyListComponent
для присвоения динамических данных списка.```javascript
Class("MyListComponent", Component, {
data:[
{ // значение этого объекта будет отображено в подкомпоненте с помощью DataGridController
name:"<имя контакта>",
email:"email@example.com",
profile_picture:"img/photo.png"
},
{ // значение этого объекта будет отображено в подкомпоненте с помощью DataGridController
name:"<имя контакта>",
email:"email@example.com",
profile_picture:"img/photo.png"
},
{ // значение этого объекта будет отображено в подкомпоненте с помощью DataGridController
name:"<имя контакта>",
email:"email@example.com",
profile_picture:"img/photo.png"
}
]
})
#### org.quickcorp.controllers.ModalController
#### org.quickcorp.controllers.FormValidations
Класс **FormValidations** используется для управления базовыми проверками формы для контроллера **FormController**.
#### Пример использования:
```html
FormValidations.getDefault(validationName)
Где validationName — это имя проверки, которое должно быть указано в свойстве validations контроллера FormController.
Определение контроллера формы предназначено для помощи в управлении динамическими формами. Используя нормализованную синтаксическую конструкцию определения контроллера формы, вы можете избежать необходимости писать сложную логику отправки формы, так как она разделена здесь на три этапа.
Это строковое имя определения класса. Контроллер формы использует функцию помощника ClassFactory для загрузки этого класса, поэтому имя может содержать полное имя пакета и определения.
Это объект с особыми свойствами формы. По умолчанию настройки следующие: backRouting:'#', loadingRouting:'#loading', nextRouting:'#signupsuccessful'. Эти настройки предназначены для управления поведением потока формы.loadingRouting — это имя маршрута, которое будет запущено во время вызова serviceClass до получения ответа от сервисного загрузчика.
backRouting — это имя маршрута, которое будет запущено, если вызов serviceClass завершится ошибкой.
nextRouting — это имя маршрута, которое будет запущено при успешном завершении вызова serviceClass.
Это объект с вспомогательными функциями проверки каждого поля формы. Когда вы определяете функцию проверки для поля, FormController будет запрашивать выполнение этой функции перед отправкой формы, если она вернёт true.
Чтобы определить проверки для полей формы, вам просто нужно добавить их как часть свойства validations.
// Допустим, что у вас есть поле формы с названием "name"
validations: {
name () {
return (fieldName, dataValue, element) => {
return [true ... или условие false];
};
},
}, //... добавьте проверку для каждого поля формы, которое требуется проверять
Вы также можете использовать FormValidations.getDefault для простоты.
// Допустим, что у вас есть поле формы с названием "name"
validations: {
name () {
return FormValidations.getDefault('name');
},
}, //... добавьте проверку для каждого поля формы, которое требуется проверять
Этот метод внутренне используется FormController для вызова serviceClass как действия отправки формы. Он привязывается к любому событию клика или прикосновения любого элемента внутри формы, имеющего CSS-класс ".submit".Пример:
<button class="submit"><p>Отправить</p></button>
Когда происходит событие клика или прикосновения вышеупомянутой кнопки, FormController
вызывает сервис, определённый в serviceClass. Это действие выполняется методом formSaveTouchHandler. Если вы хотите изменить это поведение, просто переопределите этот метод в вашем пользовательском контроллере.
Ниже представлен полный пример определения формы регистрации с использованием FormController
.
// Сначала определим сервисный класс, который будет вызван при отправке.
Class('SignupClientService', JSONService, {
name: 'signup',
external: true,
cached: false,
method: 'POST',
url: Service.basePath + 'createaccount',
withCredentials: false,
_new_: () => {
// сервис был создан
},
done: (successfulResponse) => {
// сервис загружен
_super_('JSONService', 'done').call(successfulResponse.service, successfulResponse);
console.log(successfulResponse.service.JSONresponse);
}
});
``````javascript
// Чтобы безопасно расширить FormController, мы сначала расширяем от Controller, затем используем defaultController для создания нового объекта FormController
Class('SignupFormController', Controller, {
serviceClass: 'SignupClientService',
formSettings: { /* маршруты, которые будут запущены после вызова serviceClass */
backRouting: '#',
loadingRouting: '#loading',
nextRouting: '#signupsuccessful'
},
validations: { /* определение валидации для каждого поля формы перед отправкой */
name() {
return FormValidations.getDefault('name')
},
email() {
return FormValidations.getDefault('email')
},
comment(fieldName, dataValue, element) {
return (dataValue !== '') ? true : false;
}
},
defaulController: null,
_new_: function(o) {
o.serviceClass = this.serviceClass;
o.formSettings = this.formSettings;
o.validations = this.validations;
// здесь мы создаем новый объект defaultController с использованием New FormController
// передаем объект o, который получен из процесса сборки компонентов.
this.defaulController = New(FormController, o);
},
done: function() {
// определяем пользовательскую функцию обратного вызова done для внедрения пользовательского поведения, а также вызываем поведение defaultController
logger.debugEnabled = true;
var controller = this.defaulController;
try {
controller.done.call(controller);
} catch (e) {
logger.debug('Не удалось выполнить стандартное поведение');
}
}
})
``````html
<!-- Тень компонента для отображения формы регистрации -->
<!-- шаблон: signup-form.tpl.html -->
```<form action="#" style="border: 1px solid #ccc; border-radius: 20px;">
<div class="container">
<slot name="title">
<h1>Форма регистрации</h1>
</slot>
<slot name="subtitle">
<p>Пожалуйста, заполните эту форму для запроса предложения.</p>
</slot>
<hr/>
<slot id="field_control" name="field-control">
</slot>
<hr/>
<slot name="submit_button"></slot>
</div>
</form>
```html
<!-- Форма регистрации с использованием затенённого компонента signup-form -->
<!-- Шаблон: signup.tpl.html -->
<component name="signup-form" shadowed="true" controller-class="SignupFormController">
<h1 slot="title">Форма регистрации</h1>
<p slot="subtitle">Пожалуйста, заполните эту форму для запроса предложения.</p>
<label slot="field-control" id="name_label" for="name"><b>👤 Полное имя</b></label>
<input slot="field-control" type="text" pattern="^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$" title="Введите ваше полное имя" placeholder="Полное имя" name="name" data-field="name" aria-labelledby="name_label" required>
<label slot="field-control" id="email_label" for="email"><b>📧 Электронная почта</b></label>
<input slot="field-control" type="email" pattern="^[\\w-\\. ]+@([\\w-]+\\. )+[\\w-]{2,4}$" title="Введите правильный адрес электронной почты" placeholder="Введите адрес электронной почты" name="email" data-field="email" aria-labelledby="email_label" required>
<label slot="field-control" for="comment" id="comment_label"><b>💬 Комментарий</b></label>
<textarea slot="field-control" name="comment" title="Введите комментарий" rows="10" cols="100" data-field="comment" aria-labelledby="comment_label"></textarea>
<p slot="field-control">Отправляя эту форму вы соглашаетесь с нашими <a href="#" style="color:dodgerblue">Условиями использования и политикой конфиденциальности</a>.</p>
<div class="clearfix">
<button aria-label="Отмена" onclick="location.href='javascript:void(0);'">
Отмена
</button>
<button aria-label="Отправить" onclick="location.href='javascript:void(0);'">
Отправить
</button>
</div>
</component>
``````html
<div>
<button href='/#'" role="button" tabindex="-1" type="button" class="cancelbtn">
<p>Отмена</p>
</button>
<button aria-label="Submit" role="button" tabindex="-1" type="button" class="signupbtn submit">
<p>Submit</p>
</button>
</div>
<component>
<div>
<button href='/#' role="button" tabindex="-1" type="button" class="cancelbtn">
<p>Отмена</p>
</button>
<button aria-label="Submit" role="button" tabindex="-1" type="button" class="signupbtn submit">
<p>Submit</p>
</button>
</div>
<component>
```#### org.quickcorp.controllers.SwaggerUIController
Используется для внедрения необходимого DOM для Swagger UI API. Узнайте больше в этой статье блога QCObjects Developers под названием [Работа с Swagger UI как с компонентом QCObjects](https://devblog.qcobjects.org/working-with-swagger-ui-as-a-qcobjects-component-ck6xzoqkg05indfs1i4rxq72e).
##### Пример использования:
```html
<component componentClass="SwaggerUIComponent" controllerClass="SwaggerUIController"></component>
Ниже приведены некоторые пользовательские определения эффектов, которые помогут вам создать впечатляющие визуальные возможности для ваших компонентов. Для повышения производительности эффекты изменяют CSS внутренне, чтобы применять эффект наиболее эффективным образом. А вся система эффектов основана на определении requestAnimationFrame, подробнее здесь
Перемещает объект DOM с одной позиции на другую.
Move.apply(element, xfrom, yfrom, xto, yto);
// следующая строка переместит все изображения с (0,0) на (10,10)
Tag("img").map(img => Move.apply(img, 0, 0, 10, 10));
Перемещает элемент с правой стороны по оси X в исходное положение объекта.
MoveXInFromRight.apply(element)
##### Пример:
```javascript
// следующая строка переместит каждый canvas на странице с правой стороны в исходное положение
Tag('canvas').map(canvas => MoveXInFromRight.apply(canvas));
Перемещает элемент с левой стороны по оси X в исходное положение объекта.
MoveXInFromLeft.apply(element)
// следующая строка переместит каждый canvas на странице с левой стороны в исходное положение
Tag('canvas').map(canvas => MoveXInFromLeft.apply(canvas));
Перемещает объект DOM с нижней части по оси Y в исходное положение.
MoveYInFromBottom.apply(element)
// следующая строка переместит тело каждого компонента с названием "comp1" снизу в его исходное положение
Tag('component[name=comp1]').map(componentBody => MoveYInFromBottom.apply(componentBody));
Перемещает объект DOM с верхней части по оси Y в исходное положение.
MoveYInFromTop.apply(element)
// следующая строка переместит тело каждого компонента с названием "comp1" сверху в его исходное положение
Tag('component[name=comp1]').map(componentBody => MoveYInFromTop.apply(componentBody));
Поворачивает объект по оси X.
RotateX.apply(element, angleFrom, angleTo)
```**angleFrom** и **angleTo** представляют значения угла, выраженные в градусах, от 0 до 360.
##### Пример:
```javascript
// следующая строка повернет div с id #id по оси X с 180 градусов до 240 градусов
Tag('div#id').map(div => RotateX.apply(div, 180, 240));
Поворачивает объект вокруг оси Y.
RotateY.apply(element, angleFrom, angleTo)
angleFrom и angleTo представляют значения угла в градусах, от 0 до 360.
// следующая строка повернет объект с id `#id` вокруг оси Y от 0 до 270 градусов
Tag('div#id').map(div => RotateY.apply(div, 0, 270));
Поворачивает объект вокруг оси Z.
RotateZ.apply(element, angleFrom, angleTo)
angleFrom и angleTo представляют значения угла в градусах, от 0 до 360.
// следующая строка повернет объект с id `#id` вокруг оси Z от 0 до 60 градусов
Tag('div#id').map(div => RotateZ.apply(div, 0, 60));
Поворачивает объект вокруг осей X, Y и Z одновременно, создавая эффект трехмерного поворота.
Rotate.apply(element, angleFrom, angleTo)
angleFrom и angleTo представляют значения угла в градусах, от 0 до 360.
// следующая строка повернет объект с id `#id` вокруг осей X, Y и Z от 0 до 270 градусов
Tag('div#id').map(div => Rotate.apply(div, 0, 270));
Fade.apply(element, прозрачностьОт, прозрачностьДо)
прозрачностьОт и прозрачностьДо — это числа от 0 до 1.
// следующая строка будет плавно увеличивать видимость элемента `<b class="header">` от 0.5 до 1
Tag('b.header').map(header => Fade.apply(header, 0.5, 1))
Округляет углы элемента.
Radius.apply(element, радиусОт, радиусДо)
радиусОт и радиусДо — это числовые значения.
// следующая строка округлит углы всех изображений в документе
Tag('img').map(element => Radius.apply(element, 0, 100))
Resize.apply(element, масштабОт, масштабДо)
масштабОт и масштабДо — это числовые значения. Значение 1 соответствует обычному размеру, значение 2 — удвоенному размеру, значение между 0 и 1 — меньшему масштабу.
// следующая строка создаст эффект зума вниз для каждого изображения в документе
Tag('img').map(element => Resize.apply(element, 2, 0))
// следующая строка создаст эффект зума вверх для каждого изображения в документе
Tag('img').map(element => Resize.apply(element, 0, 1))
// следующая строка создаст эффект зума вверх-вниз для каждого изображения в документе
Tag('img').map(element => Resize.apply(element, 2, 1))
WipeLeft.apply(element, scaleFrom, scaleTo)
scaleFrom и scaleTo — это числовые значения. Значение 1 соответствует обычному размеру, значение 2 — удвоенному размеру, значение между 0 и 1 — меньшему масштабу.
Tag('img').map(element => WipeLeft.apply(element, 0, 1))
Создает эффект Wipe с правой стороны до центра элемента.
WipeRight.apply(element, scaleFrom, scaleTo)
scaleFrom и scaleTo — это числовые значения. Значение 1 соответствует обычному размеру, значение 2 — удвоенному размеру, значение между 0 и 1 — меньшему масштабу.
Tag('img').map(element => WipeRight.apply(element, 0, 1))
Создает эффект Wipe снизу вверх от центра элемента.
WipeUp.apply(element, scaleFrom, scaleTo)
scaleFrom и scaleTo — это числовые значения. Значение 1 соответствует обычному размеру, значение 2 — удвоенному размеру, значение между 0 и 1 — меньшему масштабу.
Tag('img').map(element => WipeUp.apply(element, 0, 1))
Создает эффект Wipe сверху вниз от центра элемента.
WipeDown.apply(element, scaleFrom, scaleTo)
scaleFrom и scaleTo — это числовые значения. Значение 1 соответствует обычному размеру, значение 2 — удвоенному размеру, значение между 0 и 1 — меньшему масштабу.##### Пример
Tag('img').map(element => WipeDown.apply(element, 0, 1))
org.quickcorp.tools.canvas.CanvasTool
org.quickcorp.tools.layouts.BasicLayout
Ниже приведены набор заранее определённых виджетов для общего использования.
org.quickcorp.views.GridView
Общее определение GridView для использования с сетками.
Двигатель локализации QCObjects позволяет вам определять пользовательские сообщения. Узнайте больше в этой статье в блоге разработчиков под названием Локализация для ваших прогрессивных веб-приложений.
org.quickcorp.i18n_messages.i18n_messages
Используется для вызова движка локализации.
Class('i18n_messages_<custom lang>', i18n_messages, {
...
});
'use strict';
// файл: js/packages/org.quickcorp.i18n_messages.es.js
Package('org.quickcorp.i18n_messages.es', [
Class('i18n_messages_es', i18n_messages, {
messages: [
// ... ваш словарь языка здесь
{
"en": "This is a paragraph",
"es": "Esto es un párrafo"
},
{
"en": "Welcome to my new app",
"es": "Bienvenido a mi nueva app"
}
]
}),
{
_i18n_messages_es: New(i18n_messages_es)
}
]);
Чтобы начать использование встроенного сервера HTTP/2 QCObjects, просто перейдите в путь вашего проекта и выполните следующую команду в вашей консоли:
> qcobjects launch mynewapp
или
> qcobjects-server
Это запустит сервер, который будет обслуживать файлы внутри текущей директории, используя встроенный сервер HTTP/2 с базовыми настройками.
QCObjects был спроектирован для работы в профессиональной среде. Есть множество способов и парадигм, которые вы можете использовать при определении своей архитектуры программного обеспечения. Одним из рекомендованных является использование многослойной или N-слоевой архитектуры. Преимущества многослойной (Multitier) или N-слоевой архитектуры заключаются в масштабируемости и надёжности систем, требующих большего воздействия и производительности. Для углубленного изучения этих концепций расширение данного справочного документа было бы излишним, но вы можете прочитать больше о данных концепциях по следующим внешним ссылкам (только для справки и изучения):
Основной целью микросервиса является возможность компактного представления фрагмента функциональности бэкэнда в виде кода, который может вызываться удаленно с другого бэкэнда или фронтэнда. В принципе, можно разделить высокий уровень сервиса бэкэнда на множество маленьких микросервисов, которые могут выполнять задачу. Существует множество хороших примеров использования этого шаблона. Вы можете узнать больше о данной концепции по следующим внешним ссылкам (только для справки и изучения):
С помощью QCObjects вы можете писать свои микросервисы более элегантно, чисто и быстро.
Вы также можете использовать config.json с бэкэндовой стороны для настроек и кастомизации бэкэнда, особенно полезно для создания маршрутов микросервисов.
Ниже приведён пример кастомизированного файла config.json, содержащий настройки бэкэнда:
{
"documentRoot":"/home/qcobjects/projects/mynewapp/",
"relativeImportPath":"js/packages/",
"basePath":"/home/qcobjects/projects/mynewapp/",
"projectPath":"/home/qcobjects/projects/mynewapp/",
"domain":"mynewapp.qcobjects.com",
"dataPath":"/etc/qcobjects/data/",
"private-cert-pem":"/etc/letsencrypt/live/mynewapp.qcobjects.com/fullchain.pem",
"private-key-pem":"/etc/letsencrypt/live/mynewapp.qcobjects.com/privkey.pem",
"backend":{
"routes":[
{
"path":"/createaccount",
"microservice":"org.quickcorp.backend.signup",
"responseHeaders":{}
}
]
}
}
config.json
вы можете задать маршруты бэкенд-сервера для ваших микросервисов.Для каждого маршрута микросервиса требуется указать путь и строку с названием пакета микросервиса.
{
"backend": {
"routes": [
{
"path": "/createaccount",
"microservice": "org.quickcorp.backend.signup"
}
]
}
}
При настройке маршрутов бэкенд-сервера сервер QCObjects HTTP2 Built-In будет знать, как обрабатывать запросы для каждого указанного пути. Для всех остальных путей, которые не определены в настройках маршрутов бэкенд-сервера, сервер будет использовать стандартное поведение — отвечать статическим файлом, если он существует. С этим в виду можно использовать QCObjects для управления и обслуживания статических файлов или динамически генерируемых файлов, когда это необходимо.
Когда вы задаете определение маршрута бэкенд-сервера, вам нужно указать пакет микросервиса. Этот пакет микросервиса представляет собой определение пакета в QCObjects, содержащего класс микросервиса, расширяющегося от класса BackendMicroservice, уже определенного в QCObjects.
Ниже приведен пример определения пакета микросервиса, записанного в файле org.quickcorp.backend.signup.js
.
'use strict';
const fs = require('fs');
```Package('cl.quickcorp.backend.signup', [
Class('Microservice', BackendMicroservice, {
body: {
"jsonrpc": "2.0",
"result": "",
"id": 1
},
saveToFile: function (filename, data) {
logger.debug('Writing file: ' + filename);
fs.writeFile(filename, data, (err) => {
if (err) throw err;
console.log('Файл был сохранён!');
});
},
post: function (data) {
let submittedDataPath = CONFIG.get('dataPath'); // этот параметр заполняется из qcobjects-server
let filename = submittedDataPath + 'signup/signup' + Date.now().toString() + '.json';
console.log('ПОЛУЧЕННЫЕ ДАННЫЕ: ' + data);
this.saveToFile(filename, data);
}
})
]);Вышеуказанный микросервис сохраняет файл с полученными данными после POST-запроса и отвечает стандартным выходом JSON-RPC 2.0. Подробнее о спецификации JSON-RPC 2.0 читайте [здесь](https://www.jsonrpc.org/specification).
Сервер QCObjects HTTP2 Built-In вызывает метод `post()` определенного класса микросервиса только при получении POST-запроса на правильный путь, указанный в файле `config.json`, используя имя пакета как начальную точку отсчета. Чтобы позволить QCObjects понять и правильно выполнить ваши микросервисы, внутри пакета микросервиса требуется определение класса Microservice, а также это определение класса Microservice должно расширять класс BackendMicroservice, который является частью встроенных классов QCObjects.
### Генерация самоподписанного сертификата с помощью QCObjects
```shell
> qcobjects-createcert
> qcobjects create --pwa mynewapp
> qcobjects create --amp mynewapp
"use strict"; /*
Import('cl.quickcorp.model');
Import('cl.quickcorp.components');
Import('cl.quickcorp.controller');
Import('cl.quickcorp.view');
Package('cl.quickcorp', [
Class('FormValidator', Object, {
}),
]);## Шаг 2: Затем создайте некоторые сервисы, наследуемые классы, в файле js/packages/cl.quickcorp.services.js:
```javascript
".Strict";
/*
* QuickCorp/QCObjects распространяется под лицензией
* GNU Lesser General Public License v3.0
* [LICENSE](https://github.com/QuickCorp/QCObjects/blob/master/LICENSE.txt)
*
* Условия данной копyleft лицензии связаны с предоставлением полного исходного кода защищённых работ и модификаций под тем же лицензионным соглашением или GNU GPL v3. Авторские права и условия лицензии должны сохраняться. Вкладчики предоставляют явное согласие на передачу патентных прав. Однако более крупное программное обеспечение, использующее защищённое программное обеспечение через предоставленные им интерфейсы, может распространяться под другими условиями и без доступа к исходному коду для этого большего программного обеспечения.
*
* Все права защищены (C) 2015 Джейн Макучка, <correojean@gmail.com>
*
* Каждый имеет право делать и распространять точные копии данного лицензионного документа, но изменения в нём запрещены.
*/
Пакет('cl.quickcorp.service', [ Класс('FormSubmitService', JSONService, { имя: 'mySubmitService', внешний: true, закэшированный: false, метод: 'POST', сCredentials: false, url: 'https://api.github.com/orgs/QuickCorp/repos', new: function() { // сервис создан delete this.headers.charset; // не отправлять заголовок charset }, завершено: function(результат) { super('JSONService', 'завершено').call(this, результат); }, провал: function(результат) {
// TODO отрицательный случай
console.log("***** ОШИБКА");
}
})
])
```## Шаг 3: Теперь пришло время создать компоненты (cl.quickcorp.components.js)
```javascript
"strict";
/*
* QuickCorp/QCObjects licensed under
* GNU Lesser General Public License v3.0
* [LICENSE](https://github.com/QuickCorp/QCObjects/blob/master/LICENSE.txt)
*
* The terms of this copyleft license depend on the provision of full source code for licensed works and modifications under the same license or GNU GPL v3. Copyrights and licensing conditions must be preserved. Contributors provide explicit consent to patent rights. However, a larger application using licensed code through provided interfaces may be distributed under different terms without the source code for that larger application.
*
* Copyright (C) 2015 Jean Macuchka, <correojean@gmail.com>
*
* Each person is permitted to make exact copies of this license document, but modifying it is prohibited.
*/
Package('cl.quickcorp.components', [
Class('MyCustomComponent', Component, {
name: 'mycustomcomponent',
cached: false,
controller: null,
view: null,
templateURI: ComponentURI({
'COMPONENTS_BASE_PATH': Component.basePath,
'NAME_COMPONENT': 'mycustomcomponent',
'TEMPLATE_EXTENSION': 'tpl.html',
'DEFAULT_TEMPLATE': 'default'
})
})
]);
```## Шаг 4: После того как вы выполнили объявление вышеуказанных компонентов, вам теперь следует написать ваши контроллеры (cl.quickcorp.controller.js)
```javascript
"use strict";
/*
* QuickCorp/QCObjects распространяется под лицензией
* GNU Lesser General Public License v3.0
* [LICENSE](https://github.com/QuickCorp/QCObjects/blob/master/LICENSE.txt)
*
* Условия данной копировочной лицензии связаны с предоставлением полного исходного кода защищенных работ и модификаций под такую же лицензию или GNU GPL v3. Авторские права и условия лицензии должны быть сохранены. Вкладчики предоставляют явное разрешение на патентные права. Однако более крупное приложение, использующее защищенное приложение через предоставленные ему интерфейсы, может распространяться под другими условиями и без исходного кода для этого большего приложения.
*
* Всеобщие авторские права © 2cq 2015 Джон Макучка, <correojean@gmail.com>
*
* Каждому разрешено делать и распространять точные копии данного документа лицензии, но изменять его запрещается.
*/
"use strict";
Package('cl.quickcorp.controller', [
Class('MainController', Controller, {
_new_: function () {
//TODO: Implement
logger.debug('Элемент MainController инициализирован');
}
}),
Class('MyAccountController', Controller, {
component: null,
done: function () {
var controller = this;
```
```markdown
logger.debug('Элемент MyAccountController инициализирован');
this.component.body.setAttribute('loaded', true);
```},
_new_: function(o) {
// TODO: Реализовать
this.component = o.component;
}
]),
];
```
## Шаг 5: Для использования в HTML5 коде вам нужно выполнить некоторые настройки между тегами `<script>`:
```html
<script>
CONFIG.set('relativeImportPath', 'js/packages/');
CONFIG.set('componentsBasePath', 'templates/components/');
CONFIG.set('delayForReady', 1); // задержка перед выполнением первого события готовности, включает импорты
CONFIG.set('preserveComponentBodyTag', false); // не использовать тег <componentBody></componentBody>
Import('cl.quickcorp'); // это импортирует ваш основной файл: cl.quickcorp.js в путь к файлам js/packages/
</script>
```
# Инструмент командной строки QCObjects
## Использование
**qcobjects** [опции] [команда]
## Опции
-V, --version вывод номера версии
-h, --help вывод справочной информации
## Команды
**create** [опции] `<имя_приложения>` Создает приложение с `<имя_приложения>`
**publish** [опции] `<имя_приложения>` Публикует приложение с `<имя_приложения>`
**generate-sw** `<имя_приложения>` Генерирует сервисный работник `<имя_приложения>`
**launch** `<имя_приложения>` Запускает приложение
## Использование:
`$ qcobjects-cli [команда] --help`
Для получения подробной информации о команде
## Лицензия
[](https://app.fossa.com/projects/git%2Bgithub.com%2FQuickCorp%2FQCObjects?ref=badge_large)
```
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )