WEB-модуль
В версиях АСУД.SCADA 2.0 и выше доступен Web-модуль удаленного мониторинга.
Модуль (файл Web.psm) располагается в папке . \Scada\modules. По необходимости он может быть загружен с сайта tekon.ru
Модуль позволяет подключиться к ПК-диспетчера с удаленного ПК (ноутбука, смартфона, планшета) с помощью любого Web-браузера (IE, Chrome, Safari и др.) и отображает в табличной форме информацию о работе диспетчерской.
- работа с журналом событий
- отчет о текущих активных сигналах
- отчет обо всех событиях за текущие сутки
- отчет о работе программы АСУД.SCADA за последние 15 дней.
- отчет о переговорах за текущие сутки
- прослушивание выбранного переговора**
- КИО
- КУН-IP
** - доступно не для всех браузеров.
WEb-модуль работает в течение 1 часа после запуска АСУД.SCADA без ограничений. Для полноценной работы модуля требуется приобретение лицензии.
Настройка
В АСУД.SCADA перейти в режим Администрирования и выбрать меню Сервис \ Настройки.
- Диспетчерская — наименование объекта, которое будет отображаться на web-странице
- Сервер активен — флаг, определяющий активен ли модуль
- Список разрешенных IP-адресов — список адресов через запятую. В случае если поле пустое — доступ разрешен с любого IP-адреса.
- Порт — номер TCP-порта используемый модулем для приема входящих подключений. Если Пульте-ПК не установлено стороннего программного обеспечения, использующего 80 порт, рекомендуется указывать номер порта — 80.
- Логин, Пароль — имя пользователя и пароль для доступа. Если поля пустые авторизация по логину и паролю не используется.
Нажатие на кнопку Тест приведет к открытию в браузере страницы с данными модуля (если вы только что поставили флажок Сервер активен, то следует перед нажатием кнопки Тест нажать Применить).
Введение
Okapp имеет модульную структуру, которая может быть настроена индивидуально для каждой компании. Каждый модуль — это самостоятельная программа, которая может устанавливаться и обновляться независимо с помощью системного приложения «Магазин». Разработав модуль, вы можете установить его в вашей компании. Сотрудники смогут использовать установленное расширение только после назначения соответствующих прав. Если вы считаете, что модуль может быть интересен другим компаниям, использующим Oktell, то вы можете разместить его в Магазине Okapp. Модули могут быть бесплатные и платные. Информацию по размещению спрашивайте у менеджеров компании «Телефонные Системы».
Данное руководство описывает возможности и архитектуру web-модулей.
Возможности модуля
Телефония в модуле
Так как модули устанавливаются в рамках Okapp, они могут использовать предоставляемое API, в том числе и команды oktell.js. Это позволяет обращаться к Oktell, а значит работать с телефонией и вызывать доступные хранимые процедуры SQL-сервера. Все это позволяет модулю совершать и принимать звонки, добавлять участников в конференцию и менять статусы пользователей, отображать всплывающие диалоговые карточки и разнообразные модальные окна.
Таким образом, создавая необходимые расширения для вашей компании, вы сможете продублировать функции модулей стандартного клиентского приложения или реализовать недостающие функции для вашей телефонии. Прочитать про Oktell.js вы можете на сайте http://js.oktell.ru/js/about/
Собственная база данных
Если модулю необходимо хранить собственные данные, он может использовать собственную базу данных, которая создается во время установки. Все запросы в локальную таблицу выполняются от имени администратора, таким образом модуль не имеет ограничений для использования собственной БД в работе. Следует отметить, что модуль не может напрямую обращаться в другие базы данных и записывать в них действия, однако разрешается запрашивать данные и выполнять хранимые процедуры. Разработчик модуля также может предусмотреть наличие хранимых процедур, выполняющих служебные действия.
Дизайн приложения
Для разработки приложений в едином стиле программы Okapp, создан фреймворк OkCSS. Он содержит базовые стили, цвета, шаблоны расположения блоков, иконки и элементы управления. Библиотека уже встроена в Okapp. Описание и примеры использования приведены документации на сайте http://okcss.dev.oktell.ru/.
Архитектура
Каждый модуль представляет из себя ZIP-архив, в который включены следующие файлы:
- Файл манифеста в формате JSON
- Обязательный набор JS-скриптов
- Набор ресурсов HTML, CSS, изображений и дополнительных материалов, необходимых для работы приложения
- SQL-запросы для создания необходимых таблиц и хранимых процедур в БД, установки начальных значений. Все SQL-запросы выполняются один раз при установке модуля.
Файл манифеста
Файл манифеста — текстовый файл в формате json, описывающий модуль для Okapp. Без манифеста модуль не сможет установится в вашу систему. В файле должна обязательно присутствовать информация о версии, описание модуля, порядком загрузки JS-скриптов. Здесь же указывается ID модуля, которое отображается в адресной строке браузера. Более подробно смотрите в документации https://github.com/telsystems/web-modules/wiki/Manifest.json.
, "description": < "ru": "Короткое описание модуля", "en": "Short module description" >, "images": "img/screenshot.png", "oktellVersion": "2.10.1.140410", "appVersion": "0.5.1", "version": "0.2.1", "scripts": "js/all.js", "styles": "css/all.css", "wwwDir": "www", "defaultPrivileges": < "subject": < "type": 13 >, "privilegeCode": "view" >, "privileges": < "code": "contacts", "name": < "ru": "Мои контакты", "en": "My contacts" >>, "icon": "path/to/iconForMenu.png", "iconCSS": "communication-1" >
Разработка модуля
Файлы JS — основа модуля. В файлах содержится весь код для подключения и работы с модулем. Вы можете разрабатывать ваше расширение тремя способами.
На фреймворке AngularJS
Мы рекомендуем использовать именно этот способ, поскольку Okapp написан с использованием данной технологии. Фреймворк AngularJS уже изначально предназначен для разработки одностраничных приложений, благодаря чему разработка модуля значительно облегчается. Используя предоставляемое API от Okapp, вы получаете большие возможности для создания собственного веб-приложения. Используемые в работе ресурсы, такие как HTML, CSS и другие подгружаемые документы, должны располагаться в ZIP-архиве модуля.
На нативном JavaScript
Если вы не имеете опыта разработки на AngularJS, проектируйте модуль, используя другие библиотеки, возможности языка JavaScript и предоставляемое API от Okapp. Также как и в предыдущем способе, необходимо поместить все используемые ресурсы в архив проекта.
Интеграция через IFRAME
Фактически, такой модуль отображает любую веб-страницу с возможностью навигации по ней. Необходимо понимать, что такое простое отображение не дает возможности получать какие-либо вводимые данные на открытом фрейме. Примером такой реализации частично является модуль “Карточка оператора” при использовании компонента web-форма в диалоговом сценарии.
Установка модуля и прав доступа
После этапа разработки установить разработанное приложение в Okapp вы можете, выполнив следующие шаги:
Шаг 1. Установка из файла. Перейдите в «Магазин». Нажмите кнопку «Установить из файла» и выберите zip-архив модуля.
ВНИМАНИЕ: Для выполнения этого действия необходимо наличие у пользователя права «Установка/обновление приложений из файла».
Шаг 2. Назначение прав
После установки нового модуля администраторы системы автоматически получают права на использование приложения. Остальным пользователям необходимо отдельно выделить права на установленные расширения в клиентском приложении (Администрирование\Пользователи\Доступ).
После установки модуля у пользователей с правами, появляется значок в боковом меню. Следует учитывать, что некоторые приложения могут работать в фоновом режиме и появляться в меню только при возникновении каких-либо событий.
Обновление модуля происходит аналогично установке. Для обновления в файле манифеста требуется указать следующую старшую версию модуля.
Модули JavaScript
Сначала программы на JavaScript были небольшими — в прежние времена они использовались для изолированных задач, добавляя при необходимости немного интерактивности веб-страницам, так что большие скрипты в основном не требовались. Прошло несколько лет, и вот мы уже видим полномасштабные приложения, работающие в браузерах и содержащие массу кода на JavaScript; кроме того, язык стал использоваться и в других контекстах (например, Node.js).
Таким образом, в последние годы появились причины на то, чтобы подумать о механизмах деления программ на JavaScript на отдельные модули, которые можно импортировать по мере необходимости. Node.js включал такую возможность уже давно, кроме того, некоторые библиотеки и фреймворки JavaScript разрешали использование модулей (например, CommonJS и основанные на AMD системы модулей типа RequireJS, а позднее также Webpack и Babel).
К счастью, современные браузеры стали сами поддерживать функциональность модулей, о чем и рассказывает эта статья. Этому можно только порадоваться — браузеры могут оптимизировать загрузку модулей, что было бы гораздо эффективнее использования библиотеки, и взять на себя обработку на стороне клиента и прочие накладные расходы.
Поддержка в браузерах
Встроенная обработка модулей JavaScript связана с функциями import и export , которые поддерживаются браузерами следующим образом:
import
BCD tables only load in the browser
export
BCD tables only load in the browser
Пример использования модулей
Для того, чтобы продемонстрировать использование модулей, мы создали простой набор примеров, который вы можете найти на GitHub. В этих примерах мы создаём элемент на веб-странице и затем рисуем различные фигуры на нём (и выводим информацию об этом).
Примеры довольно тривиальны, но они намеренно сделаны простыми для ясной демонстрации модулей.
Примечание: Если вы хотите скачать примеры и запустить их локально, вам нужно будет запустить их через локальный веб-сервер.
Базовая структура примера
В первом примере (см. директорию basic-modules) у нас следующая структура файлов:
index.html main.js modules/ canvas.js square.js
Примечание: Все примеры в этом руководстве в основном имеют одинаковую структуру.
Давайте разберём два модуля из директории modules:
- canvas.js — содержит функции, связанные с настройкой canvas:
- create() — создаёт холст заданной ширины width и высоты height внутри -обертки с указанным id и помещённой в родителя parent . Результатом выполнения функции будет объект, содержащий 2D-контекст холста и id обертки.
- createReportList() — создаёт неупорядоченный список, добавленный внутри указанного элемента-обёртки, который можно использовать для вывода данных отчёта. Возвращает id списка.
- name — переменная со строковым значением ‘square’.
- draw() — функция, рисующая квадрат на указанном холсте с заданными размером, положением и цветом. Возвращает объект, содержащий размер, положение и цвет квадрата.
- reportArea() — функция, которая выводит посчитанную площадь квадрата в указанный список отчета.
- reportPerimeter() — функция, которая выводи посчитанный периметр квадрата в указанный список отчета.
Взгляд со стороны — .mjs против .js
В этой статье мы используем расширение .js для файлов наших модулей, но в других источниках вы можете встретить расширение .mjs . Например, в документации движка V8 используется .mjs . Причины следующие:
- Это полезно для ясности, то есть дает понять, какие файлы являются модулями, а какие — обычными JavaScript-файлами.
- Это гарантирует, что файлы вашего модуля будут проанализированы как модуль средами выполнения, такими как Node.js, и инструментами сборки, такими как Babel.
Тем не менее, мы решили продолжать использовать .js , по крайней мере на данным момент. Чтобы модули корректно работали в браузере, вам нужно убедиться, что ваш сервер отдаёт их с заголовком Content-Type , который содержит JavaScript MIME type такой как text/javascript . В противном случае вы получете ошибку проверки MIME type — «The server responded with a non-JavaScript MIME type», и браузер не сможет запустить ваш JavaScript. Большинство серверов уже имеют правильный тип для .js -файлов, но ещё не имеют нужного MIME type для .mjs -файлов. Серверы, которые уже отдают .mjs файлы корректно, включают в себя GitHub Pagesи http-сервер для Node.js.
Это нормально, если вы уже используете такую среду или ещё нет, но знаете, что делать, и имеете нужные доступы (то есть вы можете настроить свой сервер, чтобы он устанавливал корректный Content-Type -заголовок для .mjs -файлов). Однако это может вызвать путаницу, если вы не контролируете сервер, с которого отдаются файлы, или публикуете файлы для общего пользования, как мы здесь.
В целях обучения и переносимости на разные платформы мы решили остановится на .js .
Если вы действительно видите ценность и ясность использования .mjs для модулей по сравнению с использованием .js для обычных JavaScript-файлов, но не хотите столкнуться с проблемой описанной выше, вы должны всегда использовать .mjs во время разработки и конвертировать их в .js во время сборки.
Также стоит отметить, что:
- Некоторые инструменты могут никогда не добавить поддержку .mjs , например, TypeScript.
- атрибут используется для обозначения того, что файл является модулем. Вы увидите примеры использования данного атрибута ниже.
Экспорт функционала модуля
Первое, что нужно сделать, чтобы получить доступ к функционалу модуля, — экспортировать его. Это делается с помощью инструкции export .
Самый простой способ использовать экспорт — поместить конструкцию export перед любыми элементами, которые вы хотите экспортировать из модуля, например:
export const name = "square"; export function draw(ctx, length, x, y, color) ctx.fillStyle = color; ctx.fillRect(x, y, length, length); return length: length, x: x, y: y, color: color, >; >
Вы можете экспортировать var -, let -, const -переменные, и — как мы увидим позже — классы. Они должны быть в верхней области видимости, вы не можете использовать export внутри функции, например.
Более удобный способ экспорта всех элементов, которые вы хотите экспортировать,— использовать одну конструкцию export в конце файла модуля, где указать переменные, функции, классы, который вы хотите экспортировать, через запятую в фигурных скобках. Например:
export name, draw, reportArea, reportPerimeter >;
Импорт функционала в ваш скрипт
После того, как вы экспортировали некоторые функции из своего модуля, вам необходимо импортировать их в свой скрипт, чтобы иметь возможность использовать их. Самый простой способ сделать это:
import name, draw, reportArea, reportPerimeter > from "./modules/square.js";
Используйте конструкцию import , за которой следует разделенный запятыми список функций, которые вы хотите импортировать, заключённый в фигурные скобки, за которым следует ключевое слово from, за которым следует путь к файлу модуля — путь относительно корня сайта, который для нашего примера basic-modules будет равен /js-examples/modules/basic-modules .
Однако, мы написали путь немного иначе — мы используем ( . ) синтаксис, означающий «текущую директорию», за которым следует путь к файлу, который мы пытаемся найти. Это намного лучше, чем каждый раз записывать весь относительный путь, поскольку он короче и делает URL-адрес переносимым — пример все равно будет работать, если вы переместите его в другое место в иерархии сайта.
/js-examples/modules/basic-modules/modules/square.js
./modules/square.js
Вы можете найти подобные строки кода в файле main.js .
Примечание: В некоторых модульных системах вы можете опустить расширение файла и начальные / , ./ , or ../ (например ‘modules/square’ ). Это не работает в нативных JavaScript-модулях.
После того, как вы импортировали функции в свой скрипт, вы можете использовать их так же, как если бы они были определены в этом же файле. Следующий пример можно найти в main.js , сразу за строками импорта:
let myCanvas = create("myCanvas", document.body, 480, 320); let reportList = createReportList(myCanvas.id); let square1 = draw(myCanvas.ctx, 50, 50, 100, "blue"); reportArea(square1.length, reportList); reportPerimeter(square1.length, reportList);
**Примечание:**Хотя импортированные функции доступны в файле, они доступны только для чтения. Вы не можете изменить импортированную переменную, но вы всё равно можете изменять свойства у const -переменных. Кроме того, переменные импортируется как «live bindings» — это означает, что они могут меняться по значению, даже если вы не можете изменить привязку, в отличие от const .
Добавление модуля на HTML-страницу
Далее нам необходимо подключить модуль main.js на нашу HTML-страницу. Это очень похоже на то, как мы подключаем обычный скрипт на страницу, с некоторыми заметными отличиями.
script type="module" src="main.js"> script>
Вы также можете встроить скрипт модуля непосредственно в HTML-файл, поместив JavaScript-код внутрь -элемента:
script type="module">/* код JavaScript модуля *//script>
Скрипт, в который вы импортируете функционал модуля, в основном действует как модуль верхнего уровня. Если вы упустите это, то Firefox, например, выдаст ошибку «SyntaxError: import declarations may only appear at top level of a module».
Вы можете использовать import и export инструкции только внутри модулей, внутри обычных скриптов они работать не будут.
Другие отличия модулей от обычных скриптов
- Вы должны быть осторожны во время локального тестирование — если вы попытаетесь загрузить файл HTML локально (то есть по file:// URL), вы столкнётесь с ошибками CORS из-за требований безопасности JavaScript-модулей. Вам нужно проводить тестирование через сервер.
- Также обратите внимание, что вы можете столкнуться с отличным от обычных файлов поведением кода в модулях. Это происходит из-за того, что модули используют strict mode автоматически.
- Нет необходимости использовать атрибут defer (см. атрибуты элемента) при загрузке модуля, модули являются deferred по умолчанию.
- Модули выполняются только один раз, даже если на них есть ссылки в нескольких тэгах.
- И последнее, но не менее важное: давайте проясним это — функции модуля импортируются в область видимости одного скрипта, они недоступны в глобальной области видимости. Следовательно, вы сможете получить доступ к импортированному функционалу только в скрипте, в который он импортирован, и, например, вы не сможете получить к нему доступ из консоли JavaScript в DevTools. Вы по-прежнему будете получать синтаксические ошибки в DevTools, но вы не сможете использовать некоторые методы отладки, которые, возможно, ожидали использовать.
Экпорт по умолчанию против именнованого экспорта
Экспорты функций и переменных, которые мы использовали в примерах выше являются именованными экспортами — каждый элемент (будь то функция или const -переменная, например) упоминается по имени при экспорте, и это имя также используется для ссылки на него при импорте.
Существует также тип экспорта, который называется экспорт по умолчанию — это сделано для того, чтобы упростить использование экпортируемого функционала сторонним модулем, а также помогает модулям JavaScript взаимодействовать с существующими модульными системами CommonJS и AMD (это хорошо объясняется в статье ES6 в деталях: Модули от Джейсон Орендорфа — ищите по ключевому слову «Default exports»).
Давайте посмотрим на пример, и мы объясним, как это работает. В модуле square.js из нашего примера вы можете найти функцию randomSquare() , которая создаёт квардрат случайного цвета и размера со случайными координатами. Мы хотим экпортировать эту функции по умолчанию, поэтому в конце файла пишем следующее:
export default randomSquare;
Обратите внимание на отсутствие фигурных скобок.
Кстати, можно было бы определить функцию как анонимную и добавить к ней export default :
export default function(ctx) . >
В нашем файле main.js мы импортируем функцию по умолчанию, используя эту строку:
import randomSquare from "./modules/square.js";
Снова обратите внимание на отсутствие фигурных скобок. Такой синтакис допустим, поскольку для каждого модуля разрешен только один экспорт по умолчанию, и мы знаем, что это randomSquare . Вышеупомянутая строка является сокращением для:
import default as randomSquare > from "./modules/square.js";
Примечание: «as» синтаксис для переименования экспортируемых элементов поясняется ниже в разделе Переименование импорта и экcпорта.
Как избежать конфликтов имён
Пока что наши модули для рисования фигур на холсте работают нормально. Но что произойдёт, если мы попытаемся добавить модуль, который занимается рисованием другой фигуры, например круга или треугольника? С этими фигурами, вероятно, тоже будут связаны такие функции, как draw() , reportArea() и т.д.; если бы мы попытались импортировать разные функции с одним и тем же именем в один и тот же файл модуля верхнего уровня, мы бы столкнулись с конфликтами и ошибками.
К счастью, есть несколько способов обойти это. Мы рассмотрим их в следующих разделах.
Переименование импорта и экспорта
Внутри фигурных скобок инструкций import и export вы можете использовать ключевое слово as вместе с новым именем функционала, чтобы задать ему новое имя, которое вы будете использовать для него внутри модуля верхнего уровня.
Так, например, оба следующих элемента будут выполнять одну и ту же работу, хотя и немного по-разному:
// внутри module.js export function1 as newFunctionName, function2 as anotherNewFunctionName >; // внутри main.js import newFunctionName, anotherNewFunctionName > from "./modules/module.js";
// внутри module.js export function1, function2 >; // внутри main.js import function1 as newFunctionName, function2 as anotherNewFunctionName, > from "./modules/module.js";
Давайте посмотрим на реальный пример. В нашей renaming директории вы увидите ту же модульную систему, что и в предыдущем примере, за исключением того, что мы добавили модули circle.js и triangle.js для рисования кругов и треугольников и создания отчетов по ним.
Внутри каждого из этих модулей у нас есть функции с одинаковыми именами, которые экспортируются, и поэтому у каждого из них есть один и тот же оператор export внизу файла:
export name, draw, reportArea, reportPerimeter >;
Если бы в main.js при их импорте мы попытались использовать
import name, draw, reportArea, reportPerimeter > from "./modules/square.js"; import name, draw, reportArea, reportPerimeter > from "./modules/circle.js"; import name, draw, reportArea, reportPerimeter > from "./modules/triangle.js";
то браузер выдал бы ошибку — «SyntaxError: redeclaration of import name» (Firefox).
Вместо этого нам нужно переименовать импорт, чтобы он был уникальным:
import name as squareName, draw as drawSquare, reportArea as reportSquareArea, reportPerimeter as reportSquarePerimeter, > from "./modules/square.js"; import name as circleName, draw as drawCircle, reportArea as reportCircleArea, reportPerimeter as reportCirclePerimeter, > from "./modules/circle.js"; import name as triangleName, draw as drawTriangle, reportArea as reportTriangleArea, reportPerimeter as reportTrianglePerimeter, > from "./modules/triangle.js";
Обратите внимание, что вместо этого вы можете решить проблему в файлах модуля, например.
// внутри square.js export name as squareName, draw as drawSquare, reportArea as reportSquareArea, reportPerimeter as reportSquarePerimeter, >;
// внутри main.js import squareName, drawSquare, reportSquareArea, reportSquarePerimeter, > from "./modules/square.js";
И это сработало бы точно так же. Какой способ вы будете использовать, зависит от вас, однако, возможно, имеет смысл оставить код модуля в покое и внести изменения в импорт. Это особенно важно, когда вы импортируете из сторонних модулей, над которыми у вас нет никакого контроля.
Создание объекта модуля
Вышеупомянутый способ работает нормально, но он немного запутан и многословен. Существует решение получше — импортировать функции каждого модуля внутри объекта модуля. Для этого используется следующая синтаксическая форма:
import * as Module from "./modules/module.js";
Эта конструкция берёт все экспорты, доступные внутри module.js и делает их доступными в качестве свойств объекта Module , фактически давая ему собственное пространство имен. Так например:
.function1(); Module.function2();
Опять же, давайте посмотрим на реальный пример. Если вы посмотрите на нашу директорию module-objects, вы снова увидите тот же самый пример, но переписанный с учётом преимуществ этого нового синтаксиса. В модулях все экспорты представлены в следующей простой форме:
export name, draw, reportArea, reportPerimeter >;
С другой стороны, импорт выглядит так:
import * as Canvas from "./modules/canvas.js"; import * as Square from "./modules/square.js"; import * as Circle from "./modules/circle.js"; import * as Triangle from "./modules/triangle.js";
В каждом случае теперь вы можете получить доступ к импорту модуля под указанным свойством объекта, например:
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, "blue"); Square.reportArea(square1.length, reportList); Square.reportPerimeter(square1.length, reportList);
Таким образом, теперь вы можете написать код точно так же, как и раньше (при условии, что вы включаете имена объектов там, где это необходимо), и импорт будет намного более аккуратным.
Модули и классы
Как мы намекали ранее, вы также можете экспортировать и импортировать классы — это ещё один способ избежать конфликтов в вашем коде, и он особенно полезен, если у вас уже есть код модуля, написанный в объектно-ориентированном стиле.
Вы можете увидеть пример нашего модуля для рисования фигур, переписанного с помощью классов ES в нашей classes директории. В качестве примера, файл square.js теперь содержит всю свою функциональность в одном классе:
class Square constructor(ctx, listId, length, x, y, color) . > draw() . > . >
который мы затем экспортируем:
export Square >;
Далее в main.js , мы импортируем его так:
import Square > from "./modules/square.js";
А затем используем импортированный класс, чтобы нарисовать наш квадрат:
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, "blue"); square1.draw(); square1.reportArea(); square1.reportPerimeter();
Агрегирующие модули
Возможны случаи, когда вы захотите объединить модули вместе. У вас может быть несколько уровней зависимостей, где вы хотите упростить вещи, объединив несколько подмодулей в один родительский модуль. Это возможно с использованием следующего синтаксиса экспорта в родительском модуле:
export * from "x.js"; export name > from "x.js";
Для примера посмотрите на нашу директорию module-aggregation. В этом примере (на основе нашего предыдущего примера с классами) у нас есть дополнительный модуль с именем shapes.js , который собирает функциональность circle.js , square.js и triangle.js вместе. Мы также переместили наши подмодули в дочернюю директорию внутри директории modules под названием shape . Итак, структура модуля в этом примере:
modules/ canvas.js shapes.js shapes/ circle.js square.js triangle.js
В каждом из подмодулей экспорт имеет одинаковую форму, например:
export Square >;
Далее идет агрегирование. Внутри shapes.js , мы добавляем следующие строки:
export Square > from "./shapes/square.js"; export Triangle > from "./shapes/triangle.js"; export Circle > from "./shapes/circle.js";
Они берут экспорт из отдельных подмодулей и фактически делают их доступными из модуля shape.js .
Примечание: Экспорты, указанные в shape.js , по сути перенаправляются через файл и на самом деле там не существуют, поэтому вы не сможете написать какой-либо полезный связанный код внутри того же файла.
Итак, теперь в файле main.js мы можем получить доступ ко всем трём классам модулей, заменив:
import Square > from "./modules/square.js"; import Circle > from "./modules/circle.js"; import Triangle > from "./modules/triangle.js";
на единственную строку кода:
import Square, Circle, Triangle > from "./modules/shapes.js";
Динамическая загрузка модулей
Самая свежая возможность JavaScript-модулей доступная в браузерах, — это динамическая загрузка модулей. Это позволяет вам динамически загружать модули только тогда, когда они необходимы, вместо того, чтобы загружать всё заранее. Это даёт очевидные преимущества в производительности — давайте продолжим читать и посмотрим, как это работает.
Поддержка динамической загрузки модулей позволяет вызывать import() в качестве функции, передав ей аргументом путь к модулю. Данный вызов возвращает Promise , который резолвится объектом модуля (см. Создание объекта модуля), предоставляя вам доступ к экспорту указанного модуля, например:
import("./modules/myModule.js").then((module) => // делаем что-то с функционалом из импортированного модуля >);
Давайте посмотрим на пример. В директории dynamic-module-imports у нас есть ещё один пример, основанный на примере наших классов. Однако на этот раз мы ничего не рисуем на холсте при загрузке страницы. Вместо этого мы добавляем на страницу три кнопки — «Circle», «Square» и «Triangle», которые при нажатии динамически загружают требуемый модуль, а затем используют его для рисования указанной фигуры.
В этом примере мы внесли изменения только в наши index.html и main.js — экспорт модуля остается таким же, как и раньше.
Далее в main.js мы взяли ссылку на каждую кнопку, используя вызов document.querySelector() :
let squareBtn = document.querySelector(".square");
Затем мы добавляем обработчик событий на каждую кнопку, чтобы при нажатии соответствующий модуль динамически загружался и использовался для рисования фигуры:
.addEventListener("click", () => import("./modules/square.js").then((Module) => let square1 = new Module.Square( myCanvas.ctx, myCanvas.listId, 50, 50, 100, "blue", ); square1.draw(); square1.reportArea(); square1.reportPerimeter(); >); >);
Обратите внимание: поскольку выполнение Promise возвращает объект модуля, класс затем становится подкомпонентом объекта, поэтому теперь для получения доступа к конструктору нам нужно добавить к нему Module. , например Module.Square(. ) .
Устранение проблем
Вот несколько советов, которые могут помочь вам, если вам не удаётся заставить ваши модули работать. Не стесняйтесь дополнять список, если найдете что-то ещё!
- Мы упоминали об этом раньше, но повторяем: .js -файлы должны быть загружены с MIME-type равным text/javascript (или любым другим JavaScript-совместимым MIME-type, но text/javascript является рекомендованным), в противном случае вы получите ошибку проверки MIME-type, например — «The server responded with a non-JavaScript MIME type».
- Если вы попытаетесь загрузить HTML-файл локально (то есть по ссылке file:// ), вы столкнетесь с ошибками CORS из-за требований безопасности JavaScript-модулей. Вам нужно проводить тестирование через сервер. GitHub pages идеально для этого подходят, так как отдают .js -файлы с нужным MIME-type.
- Поскольку .mjs — нестандартное расширение файла, некоторые операционные системы могут его не распознать или попытаться заменить на что-то другое. Например, мы обнаружили, что macOS незаметно добавляла .js в конец файлов .mjs , а затем автоматически скрывала расширение файла. Таким образом, все наши файлы на самом деле имели название типа x.mjs.js . Когда мы отключили автоматическое скрытие расширений файлов и научили macOS принимать .mjs , всё стало в порядке.
Смотрите также
- Ипользование JavaScript-модулей в вебе, от Эдди Османи и Матиаса Байненса (англ.)
- Глубокое погружение в ES-модули в картинках, от Лина Кларка на Hacks blog (англ.)
- Глубокое погружение в ES-модули в картинках, перевод на русский язык от «Веб-стандартов»
- ES6 в деталях: Модули, статья от Джейсона Орендорфа на Hacks blog (англ.)
- Изучаем JS: Модули (англ), книга Акселя Раушмайера (англ.)
- « Предыдущая статья
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 7 авг. 2023 г. by MDN contributors.
Модуль Web-сайт (внедрение)
Создавайте и редактируйте веб-сайты компании с легкостью. С помощью этого модуля можно создавать привлекательные веб-сайты без необходимости использования сторонних инструментов или программирования.
Сроки и условия
Товар возврату и обмену не подлежит
Доставка:Стоимость модуля
Бесплатно
Модуль Веб-сайт позволяет создавать и редактировать веб-сайты компании с легкостью. С помощью этого модуля можно создавать привлекательные сайты без необходимости использования сторонних инструментов или программирования.
Стоимость внедрения
2700,00 грн
В стоимость внедрения входит 3 часа работы аналитика нашей компании для настроек модуля с последующим обучением сотрудников компании клиента работе с данным инструментом.
Описание системы:
Модуль Веб-сайт имеет встроенный визуальный редактор, позволяющий легко создавать новые страницы и редактировать имеющиеся. Вы можете добавлять текст, изображения, видео, кнопки, формы и другие элементы на страницы веб-сайта. Кроме того, модуль Веб-сайт позволяет настроить SEO параметры для каждой страницы вашего веб-сайта, что помогает обеспечить его оптимальную видимость в поисковых системах.
Основные функции
Создайте свой оригинальный сайт
С помощью удобного конструктора наполняйте свой сайт интересной и яркой информацией. Редактируйте контент в любое время без привлечения дополнительных специалистов.
Самостоятельно наполняйте свой сайт контентом
Вы легко сможете добавлять новые страницы, редактировать меню и настроить страницы в соответствии с вашими потребностями. Вам не нужно дополнительно изучать программирование, чтобы создать оригинальный адаптивный сайт своей компании.
Настраивайте SEO
С помощью функционала приложения можно легко настроить заголовок, описание и ключевые слова для каждой страницы. Это поможет вашему сайту быть на высших позициях в поисковых системах.
Хотите узнать больше о возможностях модуля?
Свяжитесь с нашими специалистами для бесплатной презентации программы
Наша компания Bon Sens рада представить нашу инновационную CRM+ERP систему на базе Odoo, специально разработанную для производственных компаний. Наша система сочетает в себе самые лучшие возможности управления отношениями с клиентами и планирования ресурсов предприятия, чтобы обеспечить эффективную и прозрачную работу вашей компании.
Благодаря модулю производства вы сможете эффективно управлять производственным процессом, планировать выполнение заказов, вести учет сырья и готовой продукции. Модуль склада поможет контролировать движение товаров и материалов, что снизит риск лишних затрат и увеличит скорость осуществления заказов.
Модуль продаж и маркетинга позволит вам эффективно взаимодействовать с клиентами, контролировать продажи и делать прогнозы на будущее. Вы сможете проводить эффективные маркетинговые кампании, следить за результативностью и получать отчеты об успешности.
Наша CRM+ERP система на базе Odoo также имеет возможности финансового управления, управления проектами, работы с отчетами и аналитикой. Все эти модули работают вместе интегрированно, чтобы обеспечить полную прозрачность и контроль всех аспектов вашего производственного бизнеса.
Наша CRM+ERP система на базе Odoo – это надежное и эффективное решение для производственных компаний, позволяющее экономить время, уменьшать затраты и повышать эффективность производства. Обратитесь к нам прямо сейчас , чтобы узнать больше о наших услугах и получить коммерческое предложение по персональным потребностям.