- PVSM.RU - https://www.pvsm.ru -
Приветствую всех.
Не знаю на сколько верно я описал данную библиотеку в заголовке, но рассказать я хочу именно о ней.
Библиотека TOM.js даёт возможность облегчить такие задачи как:
Я прекрасно осведомлен о том что есть всяческие RequireJS, klass.js и прочее, но данная библиотека представляет из себя наработки за несколько лет под конкретные задачи в проекте над которым я работаю.
Например функционал перехвата вызова функций я нигде не встречал, но нам в проекте необходим был данный функционал для разработки расширений на все случаи жизни, а позже и для других задач. А там уже и создание классов с нужным набором параметров и функций, ну и конечно же загрузчик файлов созданный с учётом специфики нашего проекта.
Изначально это была небольшая библиотека, которая за 4 года была переписана уже несколько раз из-за неприятных багов с зависимостями. В последний раз была попытка реализации загрузки при помощи RequireJS, с небольшой «надстройкой», но в итоге эта «надстройка» получилась такой закрученной (да и о зависимостях у RequireJS свои понятия) что оказалось легче реализовать свой загрузчик но уже не допуская тех ошибок которые были в прошлых реализациях.
Для загрузки «модулей» (о них я расскажу немного ниже) и скриптов можно использовать около 5 вариаций вызовов
1 способ, задача: загрузить /libraries/jquery/jquery.boot.js и /libraries/scroll/scroll.boot.js
TOM.boot.load( 'libraries/*', [ 'jquery', 'scroll' ], function( ){ } );
2 способ, задача: загрузить /jquery/jquery.boot.js
TOM.boot.load( '*', 'jquery', function( ){ } );
3 способ, задача: загрузить /jquery.boot.js
TOM.boot.load( '', 'jquery', function( ){ } );
4 способ, задача: загрузить /jquery.js
TOM.boot.load( '', 'jquery.js', function( ){ } );
5 способ, задача: загрузить code.jquery.com/jquery-1.12.0.min.js [1]
TOM.boot.load( '', 'https://code.jquery.com/jquery-1.12.0.min.js', function( ){ } );
Как можно понять по примерам — структура функции вызова следующая:
TOM.boot.load( 'путь к скрипту/модулю', 'имя файла/модуля' {строка или массив}, 'callback по окончанию загрузки' );
Логика подбора полного пути тут проста — если в имени нет расширения значит мы загружаем модуль (*.boot.js), если есть — то конкретный файл. А * (звёздочка) в пути подставляет в данное место имя модуля/файла, что позволяет сохранять понятную структуру директорий и файлов в больших приложениях.
Для начала следует разобрать что такое «модуль» в понимании данной библиотеки.
Модуль — это файл *.boot.js в котором прописаны конкретные файлы и их зависимости от других «модулей» и скриптов.
Содержимое *.boot.js выглядит следующим образом:
TOM.boot.initiate( 'button', [
{ file: '*.style.css' }, // загружаем button.style.css
{ file: '*.interface.js' }, // загружаем button.interface.js
{ file: '*.core.js', require: '*.interface.js' }, // загружаем button.core.js с зависимостью от button.interface.js
{ file: 'testButton.core.js', require: [ 'jquery', '*.core.js' ] } // загружаем testButton.core.js с зависимостями
] );
Здесь структура имеет следующий вид:
TOM.boot.initiate( 'имя модуля', 'список объектов загружаемых файлов с параметрами' );
Ну а сами объекты загружаемых файлов имеют следующую структуру:
На самом деле перехват функций будет происходить только там где Вам это необходимо, только в тех объектах которые вы «пропроксируете».
В нашем проекте например имеется 3 объекта которые прописаны в window и с которыми мы работаем, это наши так-называемые «области видимости»: api, core, interface именно с ними мы и работаем, потому только их и проксируем.
TOM.js по умолчанию создаёт core и interface, но работать с ними или нет это личное дело каждого.
Первое что необходимо сделать — это произвести «проксирование» нужных объектов подобным образом:
TOM.processor.proxy( core );
TOM.processor.proxy( interface );
Суть проксирования проста до безобразия — проходим по объекту и обёртываем функции определённым видом (добавляем pre-callback и post-callback).
После обработки нужных объектов вызванные внутри них функции- можно обрабатывать подобным образом:
// Обработка вызова создания кнопки
TOM.processor.bind( 'pre-core.test.addTestButton', function( sender )
{
// Если мы не хотим на самом деле создавать кнопку - прерываем её создание
if( !confirm( 'Действительно создать кнопку?' ) )
{
return false;
}
} );
Обработчик имеет такую структуру:
TOM.processor.bind( '{pre или post}-имя функции вызова которой ждём', 'callback функция', 'параметры' );
Помимо непосредственно возможности добавления и снятия «обработчиков», можно так-же:
TOM.processor.signal( 'момент запуска (pre/post)', 'имя функции', 'объект вызывающий функцию', 'аргументы' );
TOM.processor.one( 'перечень тех же аргументов что и в TOM.processor.bind' );
Данная часть библиотеки обыгрывает стандартный подход к созданию и наследованию классов в стандартном JavaScript, но с большим количеством нюансов и наработок.
TOM.classes.create(
'область видимости / объект в котором нужно создавать класс',
'имя создаваемого класса',
'класс от которого нужно наследоваться',
// Функция конструктор
function constructor( )
{
},
// -- Дальше идут функции в виде аргументов -- //
function foo( )
{
},
function bar( )
{
}
)
TOM.classes.create(
'область видимости / объект в котором нужно создавать класс',
'имя создаваемого класса',
'класс от которого нужно наследоваться',
// Функция конструктор
function constructor( )
{
},
// Функции в массиве или объекте
[
function foo( )
{
},
function bar( )
{
}
]
)
Кроме совместимости с TOM.processor, в созданных классах более-менее адекватно работает вызов функций из родителя, при помощи:
this.__parentCall__( ); // Вызов функции родителя исходя из arguments.callee
this.__parentFunction__( 'имя функции', 'аргументы' ); // Вызов функции по имени
И много других мелочей.
Примечание: Я знаю что arguments.callee это плохо, и оно не работает в strict mode, но пока удобной замены не придумал.
Дэмо страница: tredsnet.github.io/TOM [2]
GitHub репозиторий: github.com/tredsnet/TOM [3]
Библиотека конечно не очень подготовлена для публикации, не «вычухан» код, не убраны лишние комментарии и заметки, где-то возможно нестандартное поведение (так как тестировалось только на нашем проекте). Но всему своё время, возможно и в таком виде библиотека будет кому-то полезна, а в случае заинтересованности пользователей — возможно и развитие в нужном направлении.
Спасибо что дочитали до конца. Буду рад любым комментариям, но прошу не забывать что библиотека создавалась под конкретные нужды, конкретного проекта.
Автор: ange007
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/113462
Ссылки в тексте:
[1] code.jquery.com/jquery-1.12.0.min.js: https://code.jquery.com/jquery-1.12.0.min.js
[2] tredsnet.github.io/TOM: http://tredsnet.github.io/TOM/
[3] github.com/tredsnet/TOM: https://github.com/tredsnet/TOM
[4] Источник: https://habrahabr.ru/post/278033/
Нажмите здесь для печати.