Как стать автором
Обновить

Комментарии 64

То есть при изменении поля ввода пользователем нам его onchage (в лучшем случае) нужно вешать $digest?

А вообще очень не хватает какого-то примера кода.
В Angular не надо, надо просто связать это поле с переменной типа:
<input type="text" ng-model="somevar.somefield"/>

За это, честно говоря, Angular мне очень нравится.
Просто, честно говоря, первый раз про Angular слышу, может попадался где, но даже в памяти не отложился.
Годная статья, спасибо.

Касательно производительности — в ближайшее время это не будет вообще вызывать вопросов, потому что в новых спецификациях Ecmascript появился Object.observe. У команды AngularJS уже в планах замена (при условии поддержки браузером, конечно) dirty check на использование Object.observe().
А разве у них не появятся сразу проблемы с dependency tracking?
Я не вдавался в подробности, но главный разработчик фреймворка имеет в своем форке ветку github.com/mhevery/angular.js/tree/ObjectObserve. Значит вопрос решаемый.
Не появится, потому что проблемы dependency tracking не в обзёрверах, а в том как их готовить.
На тему databinding в AngularJS есть еще вот такой ответ на StackOverflow. В прицнипе там говорится про то же. что и в статье.
Да, я где-то это читал, и никак не мог потом найти чей это был блог. Оказывается, не блог, а StackOverflow.
Спасибо за статью! Knockout и Backbone не очень подходят для больших проектов с кучей pojo и биндингами, а тут кажется дела получше будут.
НЛО прилетело и опубликовало эту надпись здесь
Да, throttling похож на то, что используется в Angular. Загвоздка лишь в том, что его надо явно каждый раз указывать, он усложняет синтаксис, и при повсеместном его указании (а именно так бы делал я, используя Knockout, по причинам, описанным в статье) мы получаем жутко навороченный код, который при этом функционирует аналогично простому и прозрачному механизму в Angular.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Посмотрите главную страницу angularjs.org — все примеры, которые там показаны, работают как точечное использование Angular лишь в каком-то одном локальном месте на странице со своим собственным маленьким контроллером. При этом контроллеров на одной странице работает несколько штук параллельно, а в целом страница статична.

Именно в отношении модульности кода и представления Angular на голову выше Knockout, о чем я написал в начале статьи первым пунктом. Удивительно, что вы ставите этот момент в преимущество Knockout.

Цитата с главной:
AngularJS works great with other technologies. Add as much or as little of AngularJS to an existing page as you like. Many other frameworks require full commitment. This page has multiple AngularJS applications embedded in it. Because AngularJS has no global state multiple apps can run on a single page without the use of iframes. We encourage you to view-source and look around.
НЛО прилетело и опубликовало эту надпись здесь
Прошу прощения, но я снова повторю вопрос: в чем Knockout лучше индексируется, чем Angular? Любой механизм дата-биндинга вызывает одинаковые проблемы с индексацией, вне зависимости от принципа его работы.
НЛО прилетело и опубликовало эту надпись здесь
Вы просто недостаточно изучили Angular, в частности там есть директива ngBind для этого.

Вместо:

<span>{{variableValue}}</span>

можно использовать синтаксис:

<span ng-bind="variableValue">static indexed value</span>
НЛО прилетело и опубликовало эту надпись здесь
Покажите, что вы хотите видеть и как вы это делаете в KO, и я покажу аналогичную запись в Angular.
<ul ng-include="'your/dynamic/list'">
    <li>seo-friendly item1</li>
    <li>seo-friendly item2</li>
</ul>

<script type="text/ng-template" id="your/dynamic/list">
    <li ng-repeat="item in items" ng-bind="item.name"></li>
</script>

Можете поделиться опытом успешного создания (хоть какого-то) гибрида под KO, не переписывая весь процесс рендеринга на серверной части?

Я рыл, много рыл в этом направлении. Но кроме недоделок — портирования KO под nodejs — ничего дельного не нашёл.
вот про индексацию поисковиками — www.yearofmoo.com/2012/11/angularjs-and-seo.html
к тому же необязательно делать одностраничное приложение, можно встраивать в сайт (хотя придется использовать хаки типа init для инициализации начальными значениями с сервера)
НЛО прилетело и опубликовало эту надпись здесь
> если вы готовы полностью неа него проект переводить, и вам не нужна индексация поисковиками
> Известное решение. Но очень тормозное.

хмм. т.е. решение как бы есть. не сверхъестественной сложности.
да и все, что пишется на js, все равно тяжело поисковиками обрабатывается.
поэтому для блога, к примеру, не имеет смысла отрисовывать сам текст поста на javascript, но создание нового или редактирование, да и любая «админка» отлично ложится на angular
Активно использую Angular на работе и в личных проектах. Однако параллельно слежу за derbyjs. Там, как раз, с индексацией полный порядок. Его код выполняется как на сервере так и в браузере.
И что вы можете про него сказать интересного? Что вам мешает начать его использовать?
Интересное в нем то, что он ориентирован на многопользовательский класс приложений реального времени — все взаимодействие с бэкэндом происходит через socket.io. Шаблоны у него могут обрабатываться как на сервере так и на клиенте. Т.е. если запрос через ajax — отправляются чистые данные, если пользователь только что перешел по URL то все это рендерится на сервере и выдается готовая страница. Это решает проблему индексации поисковиками.
По идеологии похож на meteorjs, о котором последнее время столько шума. Но он поддерживает npm, а это большой плюс (для меня по крайней мере).
Использовать пока желания нет особого по той простой причине что он еще не production ready и многое может измениться. Однако за кодовой базой следить интересно.
Один из создателей фрейморка раньше работал как PM в команде Google Search, поэтому они активно делают упор на двойной рендеринг. Рекомендую почитать их видение в блоге blog.derbyjs.com.
Спасибо, взял на заметку.
Там можно использовать синтаксис #! который поддерживается как yandex так и google.
> Если мы изменяем данные непрерывно или большими порциями сразу, то это вызовет очень много ненужных срабатываний, ведь конечная цель — всего лишь изменить отображение, которые так или иначе будет приведено к итоговому виду, и промежуточные состояния тут не нужны.

Тут дело в том, что нужно менять observable, отвечающий за соответствующее отображение только тогда, когда вам нужно поменять отображение. Если ваше приложение меняет данные отображения во время какой-то своей внутренней работы, то это значит, что с архитектурой что-то не то: например, вы просто пожадничали ещё один observable.
Часто из того места, где меняется модель, я не могу знать, когда нужно менять отображение, а когда нет. Например, есть массив чисел, который отображается путем суммирования всех его элементов. Я могу менять элементы как по отдельности, так и все вместе в цикле, загружая новый массив. И если в первом случае можно перерисовывать отображение каждый раз, то во втором случае отображение суммы достаточно изменить один раз в конце цикла. Сам код изменения одного элемента массива может не знать о том, меняет ли он один элемент и всё, или же работает внутри какого-то цикла.

Да, вы правы, можно дать ему знать об этом созданием дополнительного слоя, но, во-первых, это усложнение архитектуры (часто уходя в сторону от разделения модели и контроллера), а во-вторых, это то, о чем написано в статье:

В совокупности такой механизм дата-биндинга создает настолько комплексно сложную систему, что другие ребята решили разрубить Гордиев узел и применить принципиально иной подход.

Работа Angular в этом отношении значительно проще и оставляет меньше места для проблем.
Реализация «события обновления» для такой структуры как массив — вообще вещь не очень очевидная, и для каждого фреймворка сугубо своя. В остальном же, я считаю, что, разрабатывая на каком-то фреймворке, нужно знать, как устроен механизм взаимодействия между разными его компонентами — это основа оптимизированного кода: не важно, knockoutjs у вас под рукой или angularjs.

К слову о дополнительных слоях. Да, действительно, это слишком усложняет. Но простой принцип «сначала сделай всё, а потом — отобрази» (не говорю о долгих операциях) обычно работает на ура.
Дело в том, что в AngularJS вообще нет «событий обновления массива» в данном случае. Есть «событие обновления суммы элементов массива», и проверка на срабатывание этого события происходит постоянно при каждой итерации dirty check, вне зависимости от того, считаем ли мы сам массив измененным или нет. Например, массив мог остаться прежним, а изменился метод подсчета суммы, и будет срабатывание dirty check, так как хотя модель осталась прежней, но её представление изменилось.
Я вам вполне верю, что для некоторых задач Angular лучше, и нигде с этим не спорю :)

Я не очень могу понять «Часто из того места, где меняется модель, я не могу знать, когда нужно менять отображение, а когда нет» и говорю о том, что это знание следует из применяемого фреймворка только и той архитектуры, которая накручена на всё это.
Да. Другими словами, фреймворк, обязывающий иметь подобное знание, не позволяет сделать по-настоящему полное разделение модели и логики работы с моделью. То есть моя позиция заключается в том, что дата-биндинг в варианте KO неизбежно ухудшает архитектуру приложения, в отличие от Angular, дата-биндинг которого дает полную свободу действий в этом плане. Единственный минус этого — производительность, а в остальном сплошные плюсы.

В дополнение, в руководстве разработчика есть еще неплохое описание, как оно там все в AngularJS работает: Conceptual Overview.
Спасибо за статью. С angular вроде все ясно. По тику пересчитывается все и готово. А вот как в ko работают dependent observables, до сих пор загадка. Они там умные, к примеру
this.computed = ko.computed(function() {
if (this.var1()) return this.var2();
return 0;
},this);
— в этом коде, если this.var1() == false, computed выражение не будет пересчитываться при изменении var2(). У вас есть идеи, как dependency tracking работает, в чем идея?
Так спрашиваете, как будто исходники закрыты :)

Там суть в следующем: все observables при инициализации выполняются (можете проверить это, добавив в них console.log, например), таким образом строится дерево зависимостей.

Это же свойство позволяет нам полезно модифицировать KnockoutJS так, чтобы сделать загрузку observables «ленивой»: сделать её таким образом, чтобы инициализация происходила не в момент инициализации вью-модели, а в момент первого обращения программиста к самой observable или к observable, от неё зависимой.
Только при обращении к самой observable, видимо? Потому как пока она не вызвана, не построено дерево, и мы не знаем, от чего она зависит.

Иногда бывает, что какая-нибудь конструкция никак в голове не уложится. Т.е. есть дерево зависимостей, по нему быстро определяется, какие computed нужно пересчитать при изменении observable. А сам computed — это что-то такое:
ko.computed = function(callback) {
var IAmInComputedObservable = true;
var computedObservableUniqId = ...;
callback();
}
И вызывается код, который в computed-переменной. Последний обращается к какой-нибудь observable, а та видит переменную IAmInComputedObservable, и это значит, что ей нужно достроить дерево зависимостей из нее на compuedObservableUniqId. И почистить которых нет. Такой смысл?
При объявлении computed, KO запускает его, и другие observable увеличивают некий счётчик типа var1_ref_count. По завершению работы computed, КО смотрит, какие счетчики увеличились и «подписывает» computed на соответствующие observables
И если не var2 не будет вычислена, то свой счетчик она не увеличит, и КО не подпишет комптютед на нее.
Решается это так: в начале компьютеда считываете нужные обсёрвеблс в переменные и работаете с ними:
this.computed = ko.computed(function() {
var var1 = this.var1();
var var2 = this.var2();
if (var1) return var2;
return 0;
},this);
НЛО прилетело и опубликовало эту надпись здесь
Хочу обратить внимание, что эти два подхода слежения за изменениями--это по сути разновидности Pull и Push парадигм работы с данными (так же как и классический http/web-sockets).
Это больше похоже на паттерны.
Спасибо за статью, я как раз не могу решить что выбрать. Не подскажите какой подход для привязки данных реализован в ember.js?
50мс — это очень дофига, если у анс идёт пересчёт при скроллинге, например, или при движении мыши
Попробуйте вывести грид на 20 колонок и 1000 строк биндингом в ангуляре.
Задержка будет порядка 500мс на core i5, ddr3.
В случае knockout ничего такого не будет.
Во-первых, этому посту полтора года.

Во-вторых, эту тему уже так часто перетирали в интернетах, что отвечать по пятнадцатому разу не имеет смысла. Просто погуглите, как на ангуляре правильно работать со scope, и чем View-Model отличается от Model в парадигме MVVM. Не бывает задачи сделать 20х1000 живых индивидуальных биндингов на одном пользовательском view, умещающемся в экран. Либо на текущем экране их будет меньше, либо биндинги будут не индивидуальные.

А в-третьих, вот.
Не так то это просто. Это как пример тормозов ангуляра, не всегда модель дайджеста хорошо используется.
По вашей ссылке ещё не реализованная фича (бета).
Если молоток использовать неправильно, им тоже можно пальцы отбить.

По вашей ссылке ещё не реализованная фича (бета).
Фича реализованная и законченная, я активно ей пользуюсь в текущем проекте. Бета — это статус сборки, а не конкретных фич. Зная динамику развития ангуляра, могу предположить, что 1.3 выйдет в stable в течение месяца-двух. Но в любом случае, вот еще вариант импровизации на тему: github.com/Pasvaz/bindonce
Если клавиатуру использовать неправильно можно и пальцы погнуть.
Бета версию использовать в продукте не считаю правильным.
Производительность хваленого в статье биндинга ангуляра от этого быстрее не становится.
Демагогия какая-то. Речь о том, что вы просто хуже знаете ангуляр, чем нокаут, и вместо того, чтобы почитать о приемах работы с ангуляром (в частности, как писать код так, чтобы ваши проблемы с производительностью вообще не возникали), вы играете словами и придираетесь к незначимым временным явлениям вроде статуса текущей сборки, которая будет неактуальна уже через месяц. Тут, извините, проблема не ангуляра, а лично ваша. Любую технологию можно заставить тормозить, если специально задаться этой целью.
Согласен. Но в статье нет ни слова о такой ситуации. Все просто гладко и идеально. Заказуха какая-то.
Я вам просто привел пример, когда ангуляр будет медленее работать со своей системой биндинга, чем knockout с событийной системой.
Странно. Цитата из статьи:
Очевидный минус этого подхода — производительность. Хотя и здесь есть небольшое исключение: например, при пакетном обновлении сразу большого количества данных проверка выполняется всего один раз в конце, а не при каждом изменении каждого из отслеживаемых объектов, как это происходит в первом случае. Но в целом, это тем не менее минус, так как при изменении всего одной переменной выполняется dirty check всех данных.

Нужно лишь понять, насколько сильны потери производительности.
Эти «приёмы» правильнее всё же называть «костылями». Агнуляр умудряется тормозить и требовать применения «приёмов» там, где более толковые решения даже не затыкаются. Рендерить только видимые ячейки хорошо, когда они все одного размера и представляют из себя плоский список. Но стоит им начать подстраиваться под размер содержимого, динамически меняться в размерах и представлять из себя иерархическую структуру, так сразу определение что видимо, а что нет становится весьма нетривиальной задачей.

И да, в более других решениях биндинги ничего не стоят (не считая небольшого потребления памяти) и их не надо отключать, лишая себя автоматической актуализации вьюшки.
Агнуляр умудряется тормозить и требовать применения «приёмов» там, где более толковые решения даже не затыкаются.

Применение «приемов» требует любой инструмент, начиная с молотка и напильника, которые надо держать под нужным углом, что тоже является приемом. Причем ангуляр требует на порядок меньшего объема приемов. Ведь в ангуляре специально думать о биндингах нужно начинать только тогда, когда их количество становится критичным для скорости работы (чтобы бывает довольно редко), а в нокауте о биндингах надо думать всё время, явно задавая и связывая цепочки observables (т.е. применяя приемы работы с технологией) по сто раз в день во время разработки. И вспоминать, где и чего забыл указать, когда что-то не заработало.

И я никак не могу понять, какая же злая сила заставляет делать 20х1000 индивидуальных биндингов, почему нельзя сделать их одним сложным биндингом? kinguru специально взял нереальный пример, чтобы продемонстрировать якобы реальный недостаток технологии.
Пример кстати вполне реальный :)
К примеру, страница печати отчета.
Простите, что снова реинкарнирую пост, но все же…
Что Вы подразумеваете под «индивидуальные биндинги» и «одним сложным биндингом». Правильно ли я понимаю, что под первыми имелось ввиду привязка каждой отдельной записи (не через ngRepeate), а под вторыми, скорее всего, — своя реализация виртуализации?
Не совсем понятно, как можно попасть в knockout на середину трекинга депов, если javascript работает в одном потоке.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории