Обновление ViewModel в ExtJs 5

Sencha добавила в ExtJs 5 крайне удобную концепцию — ViewModel. Она позволяет динамически связывать данные с представлением. Причём данные могут зависеть друг от друга и вычисляться по сложным алгоритмам. Результат кешируется, и до тех пор, пока исходные данные не поменяются, конечный результат пересчитываться и обновляться не будет. Обязательно посмотрите, если ещё не сталкивались, — очень удобная штука.

Но, к сожалению, есть случаи, когда вселенская гармония нарушается и ViewModel перестаёт вести себя как подобает. Например, когда исходные данные — Store. ViewModel не умеет подписываться на события изменения ни Store, ни вложенных объектов. И как назло, разработчики не предусмотрели метода, который позволил бы заставить ViewModel пересчитать какое-нибудь значение. В таких случаях приходится лезть в дебри реализации и искать обходные пути.

Делюсь заклинанием:

viewModel.getRoot().descend(['info']).formula.react();

Эта конструкция заставит ViewModel пересчитать значение info и обновить все связанные View. Просто подставьте название вашей формулы вместо info.

Проверено на ExtJS версий 5.0 и 5.1. Пользуйтесь и не позволяйте мелочам портить настроение.

Sencha Architect

Случилось мне тут по долгу службы столкнуться с Sencha Architect. Если кто не в курсе — это IDE, разрабатываемая Sencha для облегчения работы с её же фреймворками Sencha Touch и ExtJS. Из заявленных «killer features» в первую очередь выделяются визуальный редактор компонентов и интеллектуальная работа с кодом.

В памяти совсем юных бойцов айтишного фронта уже вероятно нет такой среды разработки, как Borland Delphi, хотя программисты постарше должны её помнить. Так вот, Sencha Architect весьма на неё похожа. Так же можно накликать себе приличный интерфейс и навешать всяких обработчиков событий на всевозможные его элементы. Но на этом сходство заканчивается.

Sencha Architect

Sencha Architect

Delphi, в отличие от Sencha Architect, позволяла сделать два шага в сторону, открыть редактор кода и сделать всё то же самое, только не прикасаясь к мышке. А тут максимум, который тебе доступен, — внутренности функции-обработчика события. Ладно-ладно, можно кликнуть в том же дереве объектов (не в коде!) и добавить произвольную функцию, но её заголовок и текст придётся править отдельно.

Редактор кода

Редактор кода

Конечно же всё это накладывает заметные ограничения на навигацию. Если ты видишь в коде свойство, которое нужно подправить, это совершенно не означает, что вот так сразу возьмёшь его и исправишь. Нет уж, будь добр, найди соответствующий объект в дереве, потом найди свойство в списке свойств этого объекта и уже там пиши своё значение. Возможно это и удобно для разработчика, который видит Sencha Touch первый раз в жизни: всё-таки не нужно долго и упорно ковыряться в документации, выискивая, как пишутся нужные свойства. Но я гораздо быстрее открою IntelliJ IDEA или WebStorm и сделаю всё то же самое, написав пару строк. Да, у меня не будет мгновенного визуального представления, да, мне придётся нажимать F5 каждый раз, чтобы проверить изменения, и да, у меня будет открыта ещё и вкладка с документацией в браузере, но это всё равно будет быстрее, чем работать с подобной системой.

Когда работаешь с IDE, специально заточенной под работу с определённым фреймворком, то ожидаешь, что эта IDE знает фреймворк от и до, но в случае с Sencha Architect это не всегда так. Например, при переименовании идентификатора связанные места не всегда обновляются автоматически, иногда придётся пробежаться ручками. Та же IntelliJ IDEA понимает зависимости между идентификаторами не в пример лучше, что уж говорить про поддержку JavaScript в целом.

За всё это Sencha хочет по 400 долларов с разработчика в год. И в цену не входят лицензии на сами фреймворки.

Итак, выводы: Sencha Architect — неплохая среда для новичков или для быстрого создания набросков. Для более сложных вещей даже Sublime Text может оказаться куда удобнее и продуктивнее.

Отладка событий в ExtJS/Sencha Touch

Иногда, когда пишешь приложение на Sencha Touch или Ext JS, очень нужно отследить порядок событий в различных компонентах и передаваемые в обработчики параметры. Зачастую это помогает лучше понять, что происходит и в самом фреймворке. Мне это тоже иногда необходимо, поэтому я написал небольшой миксин, который можно встраивать в свои компоненты.

Вариант для Sencha Touch:

Ext.define('Ext.debug.ShowEvents', {
    requires: ['Ext.mixin.Observable'],

    onClassMixedIn: function (cls) {
        cls.prototype.fireEvent = function () {
            console.log.apply(console, arguments);
            Ext.mixin.Observable.prototype.fireEvent.apply(this, arguments);
        };
    }
});

Вариант для Ext JS:

Ext.define('Ext.debug.ShowEvents', {
    requires: ['Ext.util.Observable'],

    onClassMixedIn: function (cls) {
        cls.prototype.fireEvent = function () {
            console.log.apply(console, arguments);
            Ext.util.Observable.prototype.fireEvent.apply(this, arguments);
        };
    }
});

Не забудьте указать фреймворку, где этот файл лежит. Использовать его нужно приблизительно так:

Ext.define('App.view.MyComponent', {
    extend: 'Ext.Component', 
    mixins: ['Ext.debug.ShowEvents'],

    ...
});

Вместо Ext.Component подойдет любой класс с Ext.mixin.Observable (Ext.util.Observable для Ext JS). Теперь в консоли вы увидите все события, которые генерирует этот класс.

Если что-то непонятно, можно спросить в комментариях.