Последние годы только ленивый не писал о javascript-фреймворках. AngularJS/KnockoutJS/Backbone/Ember — выбирай на вкус :) Но, озадачившись выбором фреймворка для небольшого веб-приложения с год назад, оказалось, что серебряной пули в мире js все еще не придумали.
Backbone и Ember слишком низкоуровневы и многословны, Knockout расстраивает постоянными конвертациями данных в observable, AngularJS.. да, почему бы не попробовать Angular, подумал я тогда. Энгуляр обладал приятным синтаксисом, структура Контроллеров была более менее близка и понятна и всё шло хорошо, пока.. пока мы не уперлись в довольно стандартную для Angular проблему произодительности.
Стэковерфлоу переполнен ответами на тему angular vs. performance, и лучше всего ситуацию проиллюстрируют два ответа: детальнейшее описание работы dirty-checking в Angular, сводящееся к тому, что если на странице у вас меньше 2000 элементов, то всё будет отлично (а уж 2000 элементов должно быть достаточно для каждого!). И следующий за ним контрпример, что в случае больших таблиц 2000 элементов набегают очень быстро.
В нашем случае у нас было много выпадающих списков, вроде таких: с большим количеством выпадающих элементов, значения которых были привязаны к модели. Заветные 2К элементов набежали очень быстро, и при изменении модели всё нереально тормозило (двух-трехсекундный лаг в браузере нельзя было не заметить).
В тот момент проблему мы решили низкоуровневой «затычкой» — шаблон этого «высоконагруженного» участка начали обрабатывать простейшим шаблонизатором Render.Js‘ом (или mustache‘ом, или handlebars‘ом.. да какая, в общем-то, разница? :)) и все пошло нормально, но осадочек остался…
И вот, наткнувшись на просторах интернета на любопытное видео о клиентском javascript-фреймворке React.JS, разработанный фейсбуком и делающем упор на производительности, я не мог не открыть проектик годовой давности и не попробовать переверстать проблемную область на React.
В процессе перехода React показал себя исключительно хорошо: производительность действительно на отличном уровне. Сказывается то, что «шаблонизатор» у React — это нативный javascript. А html-подобный синтаксис (такой формат у Реакта называется JSX) конвертируется в нативные вызовы при первом обращении (в production же конвертацию, безусловно, следует делать на сервере средствами Node.js).
А вот и пример шаблона в React:
<div> {navigation} <div> {activeFilters} <Filters filters1={this.state.filters1} filters2={this.state.filters2} /> </div> <div> {this.state.ViewModel.Tree.Items.length <= 0?"No results":this.state.ViewModel.Tree.Items.map(function(item) { return <div class="treeCell"> <a href={'#/' + item.Id}> <span>{item.Title} <b>[{item.ChildrenCount}]</b> <br /> <img src="{item.Image}" class="treeCellImage" /> </span> </a> </div>; })} </div> </div>
Выглядит весьма хардкорно, особенно часть, верстающая повторяющиеся элементы:
{this.state.ViewModel.Tree.Items.length <= 0?"No results":this.state.ViewModel.Tree.Items.map(function(item) { [/javascript] Что как-бы еще раз напоминает, JSX - это обычный яваскрипт. Использование виртуального DOM, за счет которого и происходит отслеживание изменений в сгенерированном html, даёт огромный прирост в производительности. Списки с 3000 элементов, которые были камнем преткновения в Angular отработали без малейших проблем. Любопытной задачей при использовании React стало взаимодействие со сторонними контролами (например, jQuery.UI или подобными). Такие контролы веб-разработчики используют каждый день, и без взаимодействия с ними нормальное внедрение js-фреймворка просто немыслимо. В React для подобных взаимодействий напрямую с DOM и сторонними компонентами существуют коллбэки, которые вызываются в случае их объявления в контроле:
- componentDidMount — вызывается по окончании первого успешного рендеринга компонента. К этому моменту DOM полностью сформирован и с ним можно работать.
- componentDidUpdate — вызывается по окончании рендеринга, если свойства (props) или состояние (state) компонента изменилось.
При желании о цикле жизни компонентов Реакта можно прочитать подробнее. В моем маленьком примере интеграция с msDropDown заключалась в объявлении метода:
componentDidUpdate: function( prevProps, prevState, rootNode) { $(rootNode).find('select').msDropDown(); },
Ну и еще один неоспоримый плюс React.JS — простота внедрения и отсутствие необходимости переписывать все веб-приложение целиком, чтобы начать его использовать. Если Энгуляр требует поклонения религии Контроллеров, Роутеров, Скоупа и прочей инъекции зависимостей с первых же минут, то Реакт упирает на выделение возможных вещей в отдельные контролы-компоненты (что видно даже на моем мини-примере), и внедрять такие контрольчики можно с легкостью в уже работающий проект малыми дозами.
Как на счет, ухода от JS в сторону C# ?
Рассмотрим на примере angularJs blog.incframework.com/ru/angularjs-vs-iml/
Я ответил комментарием к исходной статье об IML :)
Мне кажется IML в данном примере схожим с WebForms, он предлагает клиентские события, в том числе и отрисовку шаблона, отрабатывать на сервере.
Такой подход cработает для многих приложений и часто является наиболее простым. Но ReactJS и AngularJS как раз и создавались для случаев, когда необходимо сложное динамическое клиентское приложение.
И тут уйти от JS в сторону С# можно только используя что-то вроде Script#, SharpKit или похожего. Но пока использование js напрямую мне кажется всё-таки предпочтительным.
Handlebars быстрее, да и mustaches в IE 8 ( надо запускать xp, а не режим совместимости ) при вставки с выше 100 строк в таблице очень притормаживате, а то и зависает.
Ответы про IML
хотелось бы увидеть ( прочитать ) тот критерий, которые делает приложение сложным.
Основная прелесть IML в том, что позволяет уйти без использования каких то дополнительных инструментов.
Конечно, однозначный критерий сформулировать сложно. Я бы назвал «сложными» приложения с большим количеством клиентской логики, требующие наличия «состояния» (state) на клиенте.
Например, многокритериальные «калькуляторы» стоимости/кредита/страховки, ToDo-листы, CRM-системы.
Конечно, все это можно сделать и без MVVM/Angular. Просто переход к MVVM мне видится как этап эволюции в разработке. Проводя аналогии с Desktop, в WPF подход MVVM используется повсеместно, хотя программирование в «стиле» WinForms с обращением к контролам типа textBox1.Text = «123» тоже вполне возможно. MVVM выиграл за счет своего удобства и легкой возможности тестирования.
Основной вопрос — зачем уходить? Использование удобных оберток для сабмита формы на сервер и подмены блока html — ok, это безусловно полезно. Такие обертки есть у многих в виде библиотек, для этого нет необходимости переключаться на «фреймворк». Собственно, я и сам писал такое в свое время :)
dsl.Utilities.Window.Alert(«Hello»)) — а вот полезность подобных конструкций у меня уже вызывает сомнения: «больше букв», меньше гибкости (в сравнении с plain js), требует изучения.
Я собственно не к тому, что вы что-то делаете не так, или у вас «плохой фреймворк». При разработке Корпоративных информационных систем я уверен, что он дает большой выигрыш. Просто в этом посте изначально обсуждался React, и он используется скорее не в КИС, а в «модно/стильно/молодежных» приложениях. В этой сфере мне не кажется, что IML и Angular вообще конкурируют, у них разные ниши.
в WPF можно держать Connection открытым, если это «толстый клиент», а Web все таки больше адаптирован на submit form.
Интеграция типизации на всех этапах ? Вы вырезали код из контекста всего примера и конечно по этому JS вариант будет короче, но dsl.Utilites используется в 3 из 100 сценариях и это не главная особенность IML, посмотрите например blog.incframework.com/ru/power-selector/.
Вы строите мнение о IML, только по примерам кода из одной статьи, посмотрите code , live demo . Browsio это проект, который демонстрирует большую часть возможностей Incoding Framework.
Не думаю, что задачи от этого меняются, мы делали доски объявлений и системы обслуживания медицинских учреждений, но в целом те же самые JSON to HTML , потом куча манипуляций с DOM и т.д.
Я понимаю, что для изучения IML требуется время, но разве есть инструменты, которые не требуют изучения ? Я вижу IML, как аналог Nhibernate или Entity Framework, которые абстрагируют от SQL ( мы от JS ).
Опубликовали на хабре http://habrahabr.ru/post/214293/
Тем кто начинает знакомство с React.js может пригодится вот эта заготовочка проекта:
https://github.com/kriasoft/react-starter-kit
Любой хотя бы мельком видевший Ember человек знает, что это полная противоположенность «низкоуровневости и многословности».
Пиздец, долой AngularJS и Knockout
Ангуляр нужен для SPA, а Нокаут нужен для Датабайдинга:)