
Вышла версия Angular Light 0.11, которая включает много изменений.
В Angular.js, как и в старых версиях Angular Light, Scope — это механизм отслеживания изменений (Change Detector) и в нем располагаются пользовательские данные для отслеживания. Такое смешивание данных и механизма отслеживания в одном объекте породило ряд разных проблем: для таких директив как ng-if/ng-include/ng-repeat фреймворк вынужден создавать дочерние CD с прототипом к родительскому, чтобы иметь доступ к данным — это негативно влияет на расход памяти и скорость работы, но, самое важное, примеры как этот не работают как ожидается:
<div>
<input type="text" ng-model="value" /> {{value}}
<div ng-if="flag">
<input type="text" ng-model="value" /> {{value}}
<button ng-click="value=5">set</button>
</div>
</div>
ng-click=«value=5» и ng-model=«value» изменят переменную дочернего CD, которую создал ng-if, а не ту что выше. Из-за этой проблемы авторы Angular.js сделали рекомендации: не использовать данные в корне Scope (используйте имена с «точкой») и использовать controllerAs.
Так же при создании Angular 2, они учли эту проблему — теперь в нем есть отдельный тип ChangeDetector (отдельный от данных).
В Angular Light 0.11 так же внесены изменения в этом плане: бывшый Scope был разделен на ChangeDetector и пользовательские данные, — это дало дополнительную гибкость и подобные примеры (как выше) работают как ожидается:
<div>
<input type="text" al-value="value"> {{value}}
<div al-if="flag">
<input type="text" al-value="value"> {{value}}
<button al-click="value=5">set</button>
</div>
</div>
Пример на jsfiddle
Так же и с al-repeat, al-click=«active=current» внутри цикла меняет пользовательские данные, а не дочерний Scope.
<div>
{{active.name}}
<div al-repeat="current in list">
<div al-click="active=current">{{current.name}}</div>
</div>
</div>
Пример на jsfiddle
Т.к. al-repeat создает локльные переменные внутри цикла: current, $index, $last и т.п. и они не должны менять пользовательские данные (как и пересекаться с другими циклами), сделан небольшой трюк, а в Angular 2 для этого создана сложная система компиляции (не даром он весит около 1.7 Мб).
Еще одно важное новшество в Angular Light: теперь в нем есть настоящие асинхронные фильтры. Если сравнивать их с Angular.js $stateful фильтрами то можно заметить, что Angular.js вызывает ваш фильтр на каждом $digest цикле, и когда вам нужно «отправить» новое значение вы его возвращаете на следующем $digest цикле, в то время, как Angular Light не «дергает» ваш фильтр каждый раз, вы можете «отправить» новое значение в любой момент (например когда данные пришли с сервера), пример: {{user.companyId | loadCompanyName}}
al-repeat теперь может итерировать по объекту, в отличие от ng-repeat, вы можете задать сортировку.
У дериктив появился «изолированный режим», при правильном использовании это может снизить нагрузку в 100 раз, для тех кто беспокоится о dirty-checking. Так же «замороженные» массивы через Object.freeze дают ускорение dirty-checking и в планах добавление поддержки популярного immutable.js
Ускорен биндинг, теперь Angular Light стал в 2 раза быстрее чем Angular.js (в некоторых случаях), тест, что удивительно — он стал быстрее чем Basis.js, не говоря о других фреймворках.
Не знаю насколько он был нужен, но al-select был добавлен в стандартную поставку, в отличие от ng-options, al-select работает совместно с al-repeat — это дает дополнительную гибкость. Например, в одном select можно использовать несколько al-repeat циклов, или добавлять пользовательские (одиночные) пункты, пример.
alight.bootstrap был немного изменен для более удобного использования, пример:
<div id="app">
<button al-click="click()">click</button>
<input type="text" al-value="name" /> Hello {{name}}!
</div>
alight.bootstrap('#app', {
name: 'user',
click: function() {
this.name = 'world'
}
})
Пример на jsfiddle
Также внесено несколько меннее значимых улучшений. Для тех кто использовал Angular Light 0.10 и старше, есть список основных отличий.
Предыдущие статьи:
Комментарии (22)
novoxudonoser
29.11.2015 23:44+1Есть где почитать список того что нет в al по сравнению с прародителем?
lega
30.11.2015 01:21Нет модулей, констант, значений, фабрик, сервисов, провайдеров, DI, можно использовать готовые аналоги, requirejs или т.п. А если AL подключать в готовый проект, то там наверняка уже что-то используется.
Нет роутера, можно использовать один из jQuery реализация, либо сделать свой (в 30 строк), пример.
Есть асинхронные фильтры, текстовые директивы и ещё разные «плюшки», но самое главное Angular Light — библиотека, по отзывам разработчиков, с AL разработка проще и удобней.
Вакансий.
Да, это с любой малоизвестной технологией.k12th
30.11.2015 11:31Без DI все-таки грустно. Константы-модули-значения — в биореактор, нефиг бизнес-логику писать в терминах фреймворка. Но без DI получается чуть больше чем тот же knockout/ractive/rivets?
lega
30.11.2015 14:50DI можно прикрутить, кому нужно, хотя чем это лучше например такого?: myService = require('myService') который можно вызывать из любого места.
Knockout и Ractive используют observable подход (первый точно), второй через set/get. Rivets, на сколько я понял, тоже observable, но через Object.defineProperties.
Angular Light использует dirty-checking (как и Angular.js), отсюда свои плюсы и минусы, например dirty-checking не делает тяжелую обвязку (observe) вокруг данных, что дает хорошую производительность (вопреки многим мнениям). С dirty-checking вы работаете с обычными типами строки, объекты, когда в knckockout.js вам нужно заворачивать/разворачивать данные в observable объекты.
Незнаю на счет ractive/rivets, но Angular Light хорошо расширяем, например можно наследовать директивы, динамический загружать директивы, расширять систему обработки директив, есть namespaces для директив и фильтров, текстовые директивы (где ещё они есть?), можно даже сделать биндинг в стиле Ember.js — пример, и др. мелкие фичи.
Angular Light хорош для встраивания, например если ваш виджет должны размещать на других сайтах без последствий, если вы сделаете такой виджет на Angular2 то он подменить глобальные setTimeout, setInterval, requestAnimationFrame и т.п. — и чужой сайт, какой фреймворк бы там не был, будет работать через подключенный Angular 2 :(k12th
30.11.2015 14:58DI можно прикрутить, кому нужно, хотя чем это лучше например такого?: myService = require('myService') который можно вызывать из любого места.
require('myService') — это не DI, даже отдаленно (хотя модульная система вообще это must have). Строго говоря, это перпендикулярные друг другу вещи. Я-то могу прикрутить DI, а джуниор в соседнем кубикле?
Rivets, на сколько я понял, тоже observable, но через Object.defineProperties.
Не знаю, что это такое, но да, через Object.defineProperties.
Окей, я вас понял, спасибо за информацию.lega
30.11.2015 15:27Я-то могу прикрутить DI, а джуниор в соседнем кубикле?
Джуниору вообще DI не нужен, имхо, DI нужен тем кто уже созрел для него, кто понимает плюсы, а некоторым он вообще не нравится. А Angular.js пытается вывалить все свои фичи (DI, фабрики, провайдеры...) на новичков — это повышает порог входа, а я за плавное изучение новых фич.
require('myService') — это не DI, даже отдаленно
Да, но вопрос не в этом, вот и вот как requirejs можно использовать и таких обсуждений много, даже есть готовые легковесные решения. Вообщем кому надо, могут использовать готовое.k12th
30.11.2015 15:51+1а некоторым он вообще не нравится
такой, как в ангуляре, мне тоже не нравится:)
По первой ссылке чувак слабо знаком с предметом — я тоже думал, что requireJS это про DI «even if not in the most purist sense of the term» — до того, как написал первое приложение:) По второй чувак слышал звон, но не знает, где он. В первом ответе как раз раскрывается, что такое DI. Вообще, конечно, загрузка модулей может служить частью имплементации, но вообще-то этому паттерну все равно, как именно классы/инстансы попадают в область видимости.
Я вообще всецело за микробиблиотеки и собирание из легковесных решений, если что. Скорее всего, меня сбивает с толку слово Angular в названии вашей, в остальном прекрасной, библиотеки.
lega
30.11.2015 15:34+1Я, наверно, сделаю DI внешним пакетом. Некоторые «расширения» накапливаются, которые могут быть полезны другим.
lega
30.11.2015 17:01Сделал пример, как бы мог выглядеть DI в AL, зависимость указал через атрибут «inject», сервис добавил через requirejs.
k12th
30.11.2015 17:10Спасибо, но это не совсем то.
Загружу файл я сам (в 2015-то году можно уже ES2015-модули использовать, спасибо SystemJS), а вот создать инстанс класса с нужными параметрами, зарезолвив, в свою очередь, его зависимости — вот этого не хватает:(
Впрочем, для микробиблиотеки, возможно, в самый раз.lega
30.11.2015 17:22+1Спасибо, но это не совсем то.
Вот поэтому в AL и нет какой-то конретной реализации, что-бы каждый разработчик мог настроить под себя то что нужно.
SystemJS, инстанс класса...k12th
30.11.2015 17:24+1Вы никак не хотите понять, что модули и DI — это разные вещи. Я уж не знаю, как вам это выразить.
Ангуляр в свое время крепко поднагадил всем в мозги своими «модулями»:(
artemenko
30.11.2015 12:36+4После двух лет с оригинальным Angular сейчас нахожусь в полном восторге от Vue.js про Alight могу сказать что это что то среднее между ними, но синтаксис и документация Vue уверенно перетянули одеяло на себя.
baka_cirno
30.11.2015 16:01Те же впечатления. Vue.js — это Angular 1.х (точнее, его ViewModel часть), изначально сделанный правильно.
Evgeny42
CSP то запилили? :)
lega
На данный момент можно подключить notevil.js, пример, а для максимальной скорости можно сохранить кеш функций для приложения (но это ручная работа). Если включить notevil в состав AL, то он потяжелеет в 2 раза, если не больше, при том что CSP нужен не всем.
Evgeny42
Да, это же я вас надоумил попробовать прицепить CSP, пол года назад вроде. Я даже переписал приложение полностью на al, но производительность меня не удовлетворила.
lega
Почти любые «тормоза» можно оптимизировать, нужно разбираться. Есть где посмотреть ваше приложение?
Evgeny42
Скорее всего это было связано с notevil.js и тем что firefox os не понимает observe. Что очень и очень грустно.