Comments 64
Простой и понятный обзор, спасибо за публикацию!
Спасибо за статью! а продолжение будет? было бы интересно прочитать про роутера.
На данный момент есть только angular/router, и я пока не нашел времени детально с ним разобраться. uiRouter 1.0 на подходе (и он намного лучше 0.x ветки) но судя по всему сразу angular2 они поддерживать не будут.
В целом различия в роутинге и подходах с оными было бы нелпохо освятить, я согласен. Тем более что хорошие статьи которые я встречал на данный момент слегка устарели в деталях.
В целом различия в роутинге и подходах с оными было бы нелпохо освятить, я согласен. Тем более что хорошие статьи которые я встречал на данный момент слегка устарели в деталях.
UFO just landed and posted this here
На первый взгляд — да, это и побудило написать статью. Многие начинают рубить с плеча мол «ужас и кашмар». Да и я сам когда в первый раз увидел немного удивился. А разобравшись — не так страшно и есть свои плюсы. Вопросы реально возникают только с последним пунктом, так как выбор символа и способ применения не очевидны сразу.
Так же многие жалуются мол «зачем эти скобочки, почему нельзя было сделать это просто обычными атрибутами». Имеется в виду что если мы выбрали путь добавления префиксов/суффиксов то почему бы просто не сделать префикс on- и префикс bind- и т.д. И в чем-то можно согласиться, хотя с другой стороны видя подобный кусок HTML:
сразу видно где биндинги. В темплейтах побольше на поиск подобных конструкций уходит существенно меньше времени. Ну и опять же, сделав префиксы bind-/on- мы таким образом сразу бы ввели целый класс зарезервированных имет для атрибутов.
Так же многие жалуются мол «зачем эти скобочки, почему нельзя было сделать это просто обычными атрибутами». Имеется в виду что если мы выбрали путь добавления префиксов/суффиксов то почему бы просто не сделать префикс on- и префикс bind- и т.д. И в чем-то можно согласиться, хотя с другой стороны видя подобный кусок HTML:
<input
type="text"
[disabled]="isDisabled"
placeholder="Some Field"
[value]="modelValue"
required="required"
maxlength="12" />
сразу видно где биндинги. В темплейтах побольше на поиск подобных конструкций уходит существенно меньше времени. Ну и опять же, сделав префиксы bind-/on- мы таким образом сразу бы ввели целый класс зарезервированных имет для атрибутов.
> почему бы просто не сделать префикс on- и префикс bind- и т.д
Безо всяких «бы» — они есть в Angular2: «bind-attr=» вместо "[attr]=", «on-event=» вместо "(event)=" и «bindon-ngModel=» вместо "[(ngModel)]=", «var-name» вместо "#name".
> сразу видно где биндинги
Более того, сразу видно, где привязки одностороние, а где — двусторонние, а где их вообще нет. В первом ангуляре эту разницу увидеть труднее.
Безо всяких «бы» — они есть в Angular2: «bind-attr=» вместо "[attr]=", «on-event=» вместо "(event)=" и «bindon-ngModel=» вместо "[(ngModel)]=", «var-name» вместо "#name".
> сразу видно где биндинги
Более того, сразу видно, где привязки одностороние, а где — двусторонние, а где их вообще нет. В первом ангуляре эту разницу увидеть труднее.
А можно было бы наглядней:
input
.type : =text
.disabled < isDisabled
.placeholder : =Some Field
.value < modelValue
.required : true
.maxLength : 12
Это наглядно для вас. Для непосвещенного человека это целый сэт новых вещей.
А ангуляровские скобочки и звёздочки — это не сет новых вещей?
нет, потому что вы можете не пользоваться ими. Это просто сахар. Я чуть обновил текст статьи и добавил информацию об этом а так же почему именно такие скобочки были взяты за основу.
В вашем примере например не понятно в чем разница между
и
По идее же должно быть одно и то же, нет? Сначала я подумал что одно это биндинг (по аналогии с редиректом в bash) а другое — просто значение, но тогда последние два свойства не согласуются.
А в angular2 запись
намекает нам о
В вашем примере например не понятно в чем разница между
.disabled < isDisabled
и
.placeholder : =Some Field
По идее же должно быть одно и то же, нет? Сначала я подумал что одно это биндинг (по аналогии с редиректом в bash) а другое — просто значение, но тогда последние два свойства не согласуются.
А в angular2 запись
<div [inner-html]="expression"></div>
намекает нам о
div['innerHtml'] = expression();
«bindon-ngModel=» — выглядит ещё более странно, чем с сахаром.
Разница в том, что стрелочка показывает откуда куда перемещается значение (биндинг, да), а двоеточие задаёт значение по умолчанию.
Не понял, что там не согласуется?
В этом коде статическая типизация идёт лесом, да и не удобно так писать, поэтому лучше так:
И тогда вся ассоциация теряется. Тем более, что такая запись её в конец убивает:
Кроме того, у меня не укладывается в голове, как этот код:
Может быть ассоциирован с этим:
Да, именно таким, ибо чтобы ставить тут лишние скобочки и доллары, нужно быть редкостным фанатом этих символов.
Ну а уж про объявление переменных через решётку, как и вообще объявление переменных в html, я вообще молчу.
Разница в том, что стрелочка показывает откуда куда перемещается значение (биндинг, да), а двоеточие задаёт значение по умолчанию.
.disabled < isDisabled : true
Не понял, что там не согласуется?
div['innerHtml'] = expression();
В этом коде статическая типизация идёт лесом, да и не удобно так писать, поэтому лучше так:
div.innerHtml = expression();
И тогда вся ассоциация теряется. Тем более, что такая запись её в конец убивает:
[(ngModel)]="firstName"
Кроме того, у меня не укладывается в голове, как этот код:
<button (click)="doSomething($event)">
Может быть ассоциирован с этим:
element.addEventListener('click', event => doSomething(event));
Да, именно таким, ибо чтобы ставить тут лишние скобочки и доллары, нужно быть редкостным фанатом этих символов.
Ну а уж про объявление переменных через решётку, как и вообще объявление переменных в html, я вообще молчу.
Не понял, что там не согласуется?
.placeholder : =Some Field
Это типа двусторонний биндинг? В условиях хоть сколько нибудь большого проекта такие вещи довольно легко потерять извиду. Искать где там у меня двусторонние биндинги выйдет сильно тяжело.
В этом коде статическая типизация идёт лесом, да и не удобно так писать, поэтому лучше так:
начнем с того что статическая типизация вообще не причем тут. Вы наверное хотели сказать про статический анализ. Ну так с ним все хорошо так как… мы же не динамически вычисляем имя свойства. То что никто в здравом уме так не пишет — это да, но это единственная аналогия которая объясняет направление данных и при этом удобно читается (удобнее чем один символ точки, его легко не заметить).
Тем более, что такая запись её в конец убивает:
жизнь состоит из маленьких компромисов. Повторюсь — это синтаксический сахар и не более. С учетом того что теперь можно работать с формами через ngFormModel, пользоваться этой нотацией так часто вам не придется.
Да, именно таким, ибо чтобы ставить тут лишние скобочки и доллары
Доллар — это признак детали реализации. Все внутренние сервисы и объекты имеют префикс $ что бы отличать их от других. Не более.
По поводу ассоциаций — просто посмотрите какие скобочки используются в этой записи :).
Вообще у нас выходит весьма глупый спор. Вы оцениваете «интуитивность» решений исходя из своего опыта и знаний. Возьмите десяток джуниоров, покажите им ваш пример и посчитайте сколько из них разберутся что что означает.
Для меня основное преимущество использования обычного HTML в качестве основы для синтаксиса шаблонов — проще построить процесс разработки. У меня могут быть на проекте парочка толковых верстальщиков, которые могут работать с приложением и при этом не касаться JS кода. Фронтэнд разработчик же будет предоставлять им базовые конструкции на которых они уже будут реализовывать UI. Ну и серьезно, объяснить этот ML я могу за минут 15 новому разработчику, и на код ревью будет удобно следить за всем этим добром. В вашем же варианте я просто могу проглядеть какие-то мелочи при беглом ревью кода. Если бы я работал с вами — то я не особо бы парился, но мир не идеален.
Это типа двусторонний биндинг?Нет, это установка значения, а биндинги через стрелочки. Точнее это даже не биндинги, а делегирование, что эквивалентно двустороннему биндингу.
Искать где там у меня двусторонние биндинги выйдет сильно тяжело.А зачем вам искать абстрактные биндинги? Обычно всё же интересует конкретное свойство — находим его по имени, а дальше смотрим что там для него указано.
удобнее чем один символ точки, его легко не заметитьА как без точки сделать так?
.style.top < scrollTop : 0
Кстати, как Ангуляр2 вообще предлагает разруливать такие ситуации? Есть специальный синтаксис для установки стилей?
Возьмите десяток джуниоров, покажите им ваш пример и посчитайте сколько из них разберутся что что означает.В синтаксисе ангуляра точно никто не разберётся без усердного вкуривания документации. В моём, впрочем, тоже, правда синтаксис гораздо проще и единообразней (его легче запомнить).
Мой ML можно вообще за 5 минут объяснить, при этом он позволяет полностью описывать компоненты (без поведения, конечно). А сколько потребуется времени, чтобы объяснить верстальщику как создавать директивы в ангуляре, как работают скоупы, почему в именах свойств всегда должна быть точечка?
.required : true
Это очень далеко от js. Похоже на мапу, но натыкаешься на "<" и такой wtf?!
А в ts ещё и мимикрирует под объявление типа, и по-невнимательности легко перепутать с
var required: boolean
Ну а это похоже на деструктивное присваивание:
И что? Если бы тут хватало одного JS, то на JS бы и писали, а не выдумывали свои языки шаблонов.
[disabled]="isDisabled"
И что? Если бы тут хватало одного JS, то на JS бы и писали, а не выдумывали свои языки шаблонов.
деструктурированное присваивание — сильно зависит от контекста и будет смущать людей просто в JS. Вот честно пока вы не написали я бы даже не подумал об этом в таком ключе (как минимум потому что я против использования оного для переопределения значений переменных). То есть я привык именно к записи в контексте определения значения новых переменных.
Мне сложно вспомнить хтмл шаблонизатор без собственного синтаксиса. [disabled] хотя бы наглядное и по размерам больше, его легче увидеть, чем "<".
Не понимаю с чего бы свойства с биндингом должны быть более заметны, чем свойства без оного. Представьте, что в JS у нас был бы аналогичный синтасис:
Казалось бы, семантически отличаются лишь выражения справа, но синтаксически мы почему-то меняем выражение слева.
// присваиваем констатну
foo = 123
// присваиваем значение переменной
[foo] = bar
Казалось бы, семантически отличаются лишь выражения справа, но синтаксически мы почему-то меняем выражение слева.
потому что тут не совсем так
согласитесь, совершенно различная семантика присваивания. Первая запись говорит нам о простом присвоении, а вторая запись — о постоянном присвоении значения, мы гарантируем что foo всегда будет иметь значение bar. Аналог присвоения по ссылке, мы же имеем для этого обычно отдельную конструкцию:
foo = 123 // константа, обычное присвоение
[foo] = bar // интерпритируется как
watchFor('bar', () => foo = bar);
согласитесь, совершенно различная семантика присваивания. Первая запись говорит нам о простом присвоении, а вторая запись — о постоянном присвоении значения, мы гарантируем что foo всегда будет иметь значение bar. Аналог присвоения по ссылке, мы же имеем для этого обычно отдельную конструкцию:
foo &= bar;
Спасибо. Статья кардинально поменяла моё отношение к Angular2!
P.S. Поставил бы плюсик статье, если бы в карме на один голос больше было))
P.S. Поставил бы плюсик статье, если бы в карме на один голос больше было))
Как раз только что читал статью с критикой шаблонов Angular2 по сравнению с JSX React'а medium.com/@housecor/angular-2-versus-react-there-will-be-blood-66595faafd51
Вкратце — Angular 1/2 и многие другие шаблонизаторы это втаскивание JS в HTML (в более или менее кастрированном виде), подход React — втаскивание HTML в JS. При этом в JSX у нас есть весь JavaScript. Так же там был комментарий, под которым я подпишусь — «Изучая Angular, вы инвестируете своё время в Angular, изучая React, вы изучаете JavaScript»
Вкратце — Angular 1/2 и многие другие шаблонизаторы это втаскивание JS в HTML (в более или менее кастрированном виде), подход React — втаскивание HTML в JS. При этом в JSX у нас есть весь JavaScript. Так же там был комментарий, под которым я подпишусь — «Изучая Angular, вы инвестируете своё время в Angular, изучая React, вы изучаете JavaScript»
Это все популистские лозунги. По факту же и там и там смесь HTML и JS.
Посмотрим на первый попавшийся пример компонента на ReactJS: пример. Что мы тут видим.
Собственно почти то же самое что мы бы увидели в Angular2 версии. Ну то есть опять же все в одном файлике, HTML с биндингами напрямую к свойствам DOM (то есть никаких специфичных вещей учить не надо почти). Серьезно, я реально не особо вижу разницы с концептуальной точки зрения. То что мы вместо прямой работы с виртуальным DOM должны использовать директивы как элементы декларативной разметки ангуляра — я считаю это плюсом, подобные вещи чуть проще тестировать. В целом же это единственное концептуальное различие. Но если сравнивать именно Angular2 и React — различия не большие и мне это нравится. Angular первой ветки действительно отстает от всего этого сильно.
По поводу высказывания — все верно. Потому что React кроме компонентов ничего более не предоставляет. Потому все остальное — исключительно забота разработчика. Ванила JS ему в руки. Хочет пусть с нуля все делает, хочет, пусть инфраструктуру готовую использует. Свобода.
Посмотрим на первый попавшийся пример компонента на ReactJS: пример. Что мы тут видим.
Собственно почти то же самое что мы бы увидели в Angular2 версии. Ну то есть опять же все в одном файлике, HTML с биндингами напрямую к свойствам DOM (то есть никаких специфичных вещей учить не надо почти). Серьезно, я реально не особо вижу разницы с концептуальной точки зрения. То что мы вместо прямой работы с виртуальным DOM должны использовать директивы как элементы декларативной разметки ангуляра — я считаю это плюсом, подобные вещи чуть проще тестировать. В целом же это единственное концептуальное различие. Но если сравнивать именно Angular2 и React — различия не большие и мне это нравится. Angular первой ветки действительно отстает от всего этого сильно.
По поводу высказывания — все верно. Потому что React кроме компонентов ничего более не предоставляет. Потому все остальное — исключительно забота разработчика. Ванила JS ему в руки. Хочет пусть с нуля все делает, хочет, пусть инфраструктуру готовую использует. Свобода.
UFO just landed and posted this here
Ребят, я сам из реактоводов, поэтому сильно ногами не пинайте. Недавно, в силу остоятельств, пришлось активно курить первый ангуляр и периодически, по мере продвижения по developer guide, у меня на заднице шевелились волосы. Честное слово!
Большинство этих моментов было связано с шаблонами (и самый ужасающий из них, это когда я читал про передачу параметров в колбэк директивы, отмеченный амперсандом) и поэтому, наткнувшись на эту статью, с любопытством ее открыл в надежде на лучшее.
Ну что я могу сказать: уже сильно лучше, но направление так и осталось неверное. Ну реально, ребят, неужели никому из вас не кажется, что *ngIf — это ужасающе адский костыль, а присутствие таких вот вещей как раз и говорит о фундаментальных архитектурных просчетах…
Большинство этих моментов было связано с шаблонами (и самый ужасающий из них, это когда я читал про передачу параметров в колбэк директивы, отмеченный амперсандом) и поэтому, наткнувшись на эту статью, с любопытством ее открыл в надежде на лучшее.
Ну что я могу сказать: уже сильно лучше, но направление так и осталось неверное. Ну реально, ребят, неужели никому из вас не кажется, что *ngIf — это ужасающе адский костыль, а присутствие таких вот вещей как раз и говорит о фундаментальных архитектурных просчетах…
Если ngif — костыль, то что не костыль? Помесь кода и разметки? Вам это может быть и привычно, но на самом деле это выглядит странно. А ng-if это всего-лишь еще один аттрибут, чем он хуже value?
Я не про конкретно ngIf, а про дивную звездочку вначале, которая делает вообще черт знает что.
директивы, меняющие структуру DOM дерева, требуют того, что бы разработчики использовали элемент template. Вот и все. Что бы не писать
ввели звездочку, как синтаксический сахар.
вы можете не пользоваться звездочками, и иметь явную разметку. А можете пользоваться, и тогда можно будет быстро находить в темплейтах места, где происходит изменение subtree.
<template [ngIf]="expression">
<span>Conditional HTML</span>
</template>
ввели звездочку, как синтаксический сахар.
<span *ngIf="expression">Conditional HTML</span>
вы можете не пользоваться звездочками, и иметь явную разметку. А можете пользоваться, и тогда можно будет быстро находить в темплейтах места, где происходит изменение subtree.
Ну, если не пользоваться * то вместо вот этого:
придется писать вот это:
Тут меня пугает очередная непонятная переменная $implicit))
<todo-cmp *ngFor="#t of todos; #i=index" [model]="t" [index]="t"></todo-cmp>
придется писать вот это:
<template ngFor [ngForOf]="todos" #t="$implicit" #index="i">
<todo-cmp [model]="t" [index]="i"></todo-cmp>
</template>
Тут меня пугает очередная непонятная переменная $implicit))
Не костыль — это с разделением вёрстки и логики. Например:
Вёрстка:
Логика:
И верстальщих счастлив, что у него нет логики, и программист рад, что не надо лезть в вёрстку.
Вёрстка:
$mol_spoiler : $mol_block child
< switcher : $mol_button
child < title : null
eventClick < eventToggle : null
< content : null
Логика:
get child( ){ return [
this.switcher ,
this.expanded ? this.content : null ,
] )
И верстальщих счастлив, что у него нет логики, и программист рад, что не надо лезть в вёрстку.
упаси меня сатана от проектов с подобными «разметками».
А что плохого в подобной разметке кроме вашего нежелания разобраться в синтаксисе? Попытка скрестить ужа с ежом как в Ангуляре — сильно лучше?
нежелания разобраться в синтаксисе?
Моя субъективная оценка — синтаксис непроработан до конца и нуждается в «чистке». Скажем не совсем понятно зачем постоянно писать дефолтное значение (это же оно там?) даже если его нет (null), или child — это что-то типа кострукция для определения вложенности? А зачем?
И да, мне нравится то что получилось у ребят из ангуляра. Вы не подумайте, больше решений разных, но конкретно вот это — как по мне путь в никуда. С учетом того что есть довольно много неплохих вариантов описания DSL для UI и т.д. И мне в качестве оного более чем нравится html с особенностями (шаблоны ангуляра — валидный HTML)
Предложения по улучшению всегда приветствуются. Насчёт null по умолчанию — так было бы практичней, согласен. child — обычное свойство, их может быть и много, в отличие от html:
Аргумент про разделение вёрстки и логики — мимо кассы?
$mol_spolier_demo : $mol_spoiler
title : $mol_icon type < iconType : =expand
content : $mol_demo_filler
Аргумент про разделение вёрстки и логики — мимо кассы?
Ну кому-то больше нравится собирать интерефейс из кусочков, разложенных по переменным:
Не говоря уж о всей мощи JS:
Представляю, что там в render будет в сколько-нибудь больших проектах, если по рукам сильно не бить и искуственно не ограничивать «всю мощь JS в HTML».
var loginButton;
if (loggedIn) {
loginButton = <LogoutButton />;
} else {
loginButton = <LoginButton />;
}
return (
<nav>
<Home />
{loginButton}
</nav>
);
Не говоря уж о всей мощи JS:
return (
<section>
<h1>Color</h1>
<h3>Name</h3>
<p>{this.state.color || "white"}</p>
<h3>Hex</h3>
<p>
{(() => {
switch (this.state.color) {
case "red": return "#FF0000";
case "green": return "#00FF00";
case "blue": return "#0000FF";
default: return "#FFFFFF";
}
})()}
</p>
</section>
);
Представляю, что там в render будет в сколько-нибудь больших проектах, если по рукам сильно не бить и искуственно не ограничивать «всю мощь JS в HTML».
Вот вам бы как раз я по рукам-то и дал)
Пример 1:
… а в большинстве случаев лучше даже так:
Пример 2:
Вот она — вся МОЩЬ JS в HTML!)
Пример 1:
return (
<nav>
<Home />
{loggedIn ?
<LogoutButton />
:
<LoginButton />
}
</nav>
);
… а в большинстве случаев лучше даже так:
render() {
const { isLoggedIn } = this.props;
return (
<nav>
<Home />
{loggedIn ?
this.renderSomething()
:
this.renderSomethingElse()
}
</nav>
);
}
renderSomething() {
return (
<LogoutButton />
);
}
renderSomethingElse() {
return (
<LoginButton />
);
}
Пример 2:
const COLORS_IN_HEX = {
red: '#FF0000',
green: '#00FF00',
blue: '#0000FF'
};
render() {
const { color } = this.state;
return (
<section>
<h1>Color</h1>
<h3>Name</h3>
<p>{color || 'white'}</p>
<h3>Hex</h3>
<p>
{this.getColorInHex(color)}
</p>
</section>
);
}
getColorInHex(color) {
return COLORS_IN_HEX[color] || '#FFFFFF';
}
Вот она — вся МОЩЬ JS в HTML!)
Это не мне — это документации React-а.
А чего там мощного, вы фактически и идете по пути ограничения всея мощи, чтобы if-ов не было (только тернарный оператор), switch-ей тоже, т.е. искусственно накладываете ограничения на используемый синтаксис.
А чего там мощного, вы фактически и идете по пути ограничения всея мощи, чтобы if-ов не было (только тернарный оператор), switch-ей тоже, т.е. искусственно накладываете ограничения на используемый синтаксис.
А я бы за тернарный оператор бил по рукам. Вариант приведенный в документации мне лично нравится больше.
Мне нравится подход react-а, но для моих задач angular подходит как мне кажется больше, да и некоторые аспекты он делает намного проще (а некоторые сложнее, не спорю).
Мне нравится подход react-а, но для моих задач angular подходит как мне кажется больше, да и некоторые аспекты он делает намного проще (а некоторые сложнее, не спорю).
но направление так и осталось неверное
Для того что бы ваш комментарий был более конструктивным, расскажите, какое по вашему направление было бы верным и удобным? Ну вот серьезно. Давайте разберемся.
Oсновное концептуальное различие React и Angular — derty checking, а точнее на каком этапе кто из них его запускает. Angular следит за состоянием данных, React — за виртуальным DOM. Проследим жизненный цикл одной итерации изменений у каждого.
React представляет UI как композицию компонентов, каждый из которых представлен чистой функцией. На вход функции мы подаем кусок состояния, на выход — кусочек виртуального DOM. Из всех кусочков потом можно сформировать цельное представление, а derty checking происходит за счет сравнение того DOM что бы с тем что у нас сейчас, после чего React генерит патч, который применяется к реальному DOM наиболее эффективным образом. О преимуществах, которые это дает, поговорим чуть чуть позже.
Angular — тут пошли стандартным путем, и вставили dirty checking между view и моделью (как в классическом MVVM). Шаблоны в этом случае являются декларативной разметкой, описывающей как должен выглядеть UI в зависимости от состояния данных. Вместо того что бы лесть в DOM руками, нам предоставляют директивы, которые вешают биндинги и отслеживают состояния данных, и адаптируют UI под них.
Время обновления UI у ангуляра и реактор по сути зависит от одного и того же параметра — количество элементов, задействованных в dirty checking цикле. Если сравнивать первую версию angularjs и react, то и там и там весьма примитивная реализация оного. Берем все и сравниваем со всем. При такой реализации преимущество несомненно на стороне React так как мы имеем весьма простое сравнение элементов (в то время как в angular в выражениях разработчик сам прописывает за чем следить и может описать более чем странные конструкции, и не забываем о фильтрах которые замедляют derty checking). Намного меньше подводных камней при реализации приложения. В Angualr2 отслеживание изменений носит уже более реактивных характер, потому таких проблем как в angular1 это не вызывает.
То есть для меня лично концепция, лежащая в основе ангуляра, если ты правильно описал UI в декларативных шаблонах, то тебе надо просто проследить что ты правильно составляешь состояние. Это немного развязывает руки в плане процессов. Я могу вынести из компонентов шаблоны в отдельные html или jade файлы, и дать доступ на редактирование этого добра какому-нибудь верстальщику, что бы тот уже занимался рутиной вроде подгонки UI под все браузеры и т.д. Это существенно упрощает разделение труда. Ну и аспект с тестированием. Что бы протестировать приложение на angular мне по сути надо проверить что во view экспоузится нужное состояние. И для меня это наиболее ценная штука, поскольку тесты становится намного проще писать, а логика полностью отвязана от UI. Я пока не видел достаточно приложений на react, потому моя выборка может быть нерепрезентативной, но для меня тестирование компонентов в react выглядит намного более неудобным нежели в angular. Хотя плохо и неудобно можно сделать всегда.
Нет-нет, вы не поняли, я говорил лишь про view-layer. Что меня ужаснуло в первом ангуляре и от чего так и не избавились во втором — это изобретение своего собственного неочевидного синтаксиса шаблонов.
В качестве примера достаточно взглянуть на ngOptions: само существование такой директивы заставляет насторожиться.
«Это же простая итерация по массиву объектов! Зачем она вообще?» — спросит реактовод.
«А затем, что иначе вы не сможете в значение option передать что-то кроме строки!»
«Ну, знаете ли...»
Или еще один пример (о котором я писал выше) про передачу параметров в колбэк директивы, отмеченный амперсандом.
Для этого надо вызвать ее с объектом в качестве параметра, ключи которого магическим образом превратятся в переменные, доступные в скоупе (js-скоупе) этого колбэка…
Я перечитывал это раз 10, потому что просто не верил своим глазам.
«Какого хрена вообще?!» — спросит реактовод.
«Ну, потому что по-другому сделать не получилось...»
«Ну, знаете ли...»
В качестве примера достаточно взглянуть на ngOptions: само существование такой директивы заставляет насторожиться.
«Это же простая итерация по массиву объектов! Зачем она вообще?» — спросит реактовод.
«А затем, что иначе вы не сможете в значение option передать что-то кроме строки!»
«Ну, знаете ли...»
Или еще один пример (о котором я писал выше) про передачу параметров в колбэк директивы, отмеченный амперсандом.
Для этого надо вызвать ее с объектом в качестве параметра, ключи которого магическим образом превратятся в переменные, доступные в скоупе (js-скоупе) этого колбэка…
Я перечитывал это раз 10, потому что просто не верил своим глазам.
«Какого хрена вообще?!» — спросит реактовод.
«Ну, потому что по-другому сделать не получилось...»
«Ну, знаете ли...»
В качестве примера достаточно взглянуть на ngOptions
ну тут соглашусь, это компромис для достижения простой цели — UI как декларативная разметка. В React мы можем использовать все что захотим для формирования DOM (виртуального) а уж как оно в реальности будет рендриться не наша забота. А если ты хочешь сделать UI полностью декларативным, придется придумывать такие вот кастыли. И не могу сказать что это совсем уж что-то страшное.
Или еще один пример (о котором я писал выше) про передачу параметров в колбэк директивы
Тут уже попроще. Это не «коллбэк» директивы. Ну тоесть по сути это он родимый и есть, но не совсем так. Это выражение (опциональное обычно), которое имеет возможность запускать директива не теряя при этом изоляции. Ну то есть прямой аналог тут будет:
function link(scope, element, attrs) {
scope.$apply(attrs.onClick);
}
А что до передачи в качестве аргументов объекта — это контекст, в котором выполняется выражение. Задача директивы, предоставить выражению контекст, содержащий данные. Это позволяет здорово изолировать систему и снизить связанность.
Выражения в angular это такой безопасный eval, контекстом которого мы можем управлять (eval это плохо не потому что динамически выполняется что-то, а потому что мы не можем управлять контекстом и ограничивать сайд эффекты).
В общем, когда ребята из двух лагерей подружатся и общими усилиями заменят ангуляроские шаблоны+фильтры+директивы+контроллеры реактом на моей улице наступит праздник))
на моей улице наступит праздник))
А я буду грустить. Я хочу что бы мой UI был полностью декларативен, что бы его можно было валидировать исключительно статическими анализаторами, а тестировать только логику обработки данных. Что бы я мог посадить любого верстальщика что бы он занимался исключительно стилями. Собственно поэтому я на реакт так и не перелез и не планирую.
А то что двум лагерям надо меньше враждовать и больше обсуждать схожие вещи и как можно улучшить дела — это да. Этого нехватает.
«Это же простая итерация по массиву объектов! Зачем она вообще?» — спросит реактовод.
«А затем, что иначе вы не сможете в значение option передать что-то кроме строки!»
«Ну, знаете ли...»
А как это будет выглядет в реакте?
Angular 2 не решил главную проблему — неконтролируемую связность директив\модулей, что по сути имеется в MV* архитектурах тоже. Даже опытные разработчики, смешивая директивы, используя scope и другую магию, вставляют новые «подпорки» для удовлетворения новых требований. Новый синтаксис лишь уменьшил возможность подобных манипуляций, но я чувствую, что Angular все еще испорчен.
неконтролируемую связность директив\модулей, что по сути имеется в MV* архитектурах тоже
Можете пояснить? Ибо я не особо понимаю о чем вы. Ибо никаких проблем с неконтролируемой связностью в angular2 нет, ну либо я уже отношусь к той категории людей которые не используют в ангуляре скоуп и «магию» со времен angular 1.2 и потому мне сложно понять о чем вы.
Angular 2 все еще поддерживает аттрибутивные директивы (а старый еще и классовые). В итоге можно было получить что-то типа
и каждая примешивала свой функционал, что не разберешь, откуда что берется. Также старый Angular использовал $scope (или даже $rootScope), и люди ошибочно его использовали для связи компонентов между собой, в новом заменено на this, однако я не знаю, насколько они различны
<main-directive sub-directive1 subdirective2><main-directive>
и каждая примешивала свой функционал, что не разберешь, откуда что берется. Также старый Angular использовал $scope (или даже $rootScope), и люди ошибочно его использовали для связи компонентов между собой, в новом заменено на this, однако я не знаю, насколько они различны
Простите, но вы своё оружие не тем концом держите, много чего можно наворотить нарушив goodpractices. В голову даже не лезет зачем так делать как вы написали, в том смысле, какую от этого можно получить пользу.
В голову даже не лезет зачем так делать как вы написали
Вы писали на angular 1.0? в те времена подругому никак нельзя было. И в 1.1. В 1.2 уже можно было отказаться от скоупа в контроллерах, но в директивах еще было неудобно. в 1.3 уже можно было делать полноценные компоненты, а удобно это станет только с выходом 1.5.
Ну и да — у Angular 1.x ужасная документация. Ну то есть 3-4 года назад это было ок, и на фоне всего остального было круто. Но сегодня… ужас дикий, причем официальная дока и примеры никак не придерживаются этим самым goodpractices. А потому людей сходу учили плохим вещам.
Я очень рад что документация Angular2 в этом плане намного более качественнее сделана. Но примеры еще можно было бы порефакторить.
все еще поддерживает аттрибутивные директивы
Да, суть в простом разделении. Компоненты — существительные, сущности, отдельные UI компоненты. Атрибутивные директивы — прилагательные, декораторы для компонентов. Простой пример — компонет input и декоратор required добавляющий валидацию, расширяющий поведение компонента.
Лично мне подобное разделение нравится, так как оно пораждает меньше сложности и позволяет удобно расширять функционал компонентов. Но не думаю что эту фичу будут часто юзать.
Что до классовых директив — полностью согласен. Я к слову знаю пару людей которые расстроены тем что в angular2 так больше нельзя. Благо после пары холиваров они угомонились и приняли что это не ок вариант.
что не разберешь, откуда что берется
Если соблюдать правила (компонент — существительное, директива — прилагательное) и нормально именовывать директивы — то все довольно ок. Но да, я согласен что сделать плохо можно.
Также старый Angular использовал $scope (или даже $rootScope), и люди ошибочно его использовали для связи компонентов между собой
О да, и тут больше даже грех документации. Где-то с версии 1.3 angular можно вообще не использовать $scope (собственно я его не особо часто использую уже с версии 1.2 с введением controllerAs). Документация до сих пор преподносит инфу 2012-ого года как актуальную, хотя в best pratice и style guide хотя бы описано что это не ок идея. И что использовать $broadcast/$emit для общения своих директив это не ок говорится.
Я полагаю, что если бы в 2013-ом году обновили документацию и PhoneCat туториал под существующие уже на тот момент бэст практисы, проблем было бы меньше. Все же большинство сразу после полу часа чтения документации (который описывает именно $scope и подход с контроллерами) идут писать приложеньки а бэст практис — ну их.
В angular2 такой проблемы нет, все «плохое» спрятаны глубоко внутри.
Все это верно. Я собственно не спорю, а привел примеры, как можно испортить хороший фреймворк, если его плохо готовить. По-моему, многих разработчиков лучше ограничить изначально возможностями технологии, чем просить их следовать хорошим практикам (если есть кому просить). Хорошо, что в Angular 2 большая часть болезней вылечена, но бренд уже испортил себе репутацию. Есть еще и другие аспекты, которые мне не нравятся в Angular, но это уже на вкус и цвет. К примеру, декларативный язык выглядит приятнее с первого взгляда, но если в него положить много (кстати, сколько это), то читать его становится невозможно, плюс отладка тяжелая, что отмечается тут. Также у меня плохие отношения с двухсторонним биндингом. Опять же, это не явные недостатки, а вкусы
но если в него положить много (кстати, сколько это)
По этой причине мне нравятся инлайн шаблоны (с ES6 это удобно), так как проще контролировать разбухание. В целом большие шаблоны можно посчитать техническим долгом и зарефакторить позже. В некоторых случаях дробить UI на компоненты слишком дотошно может быть оверхэдом. Все зависит от контекста, за что мне ангуляр и нравится.
Я стараюсь дробить компоненты таким образом, что бы они становились реально реюзабельными и помещались в один экран (с учетом ограничения по длине строки).
плюс отладка тяжелая
А вот тут статья немного лукавит. Как я отметил в статье, ангуляр теперь будет выкидывать ошибки при компиляции шаблонов и выполнении выражений (а не молчать как в 1.x затрудняя отладку). То есть выражение
{{foobar.test}}'
в случае если foobar не объект, будет падать с TypeError и т.д.Ну и да, планируется сделать отдельно AOT компилятор, позволяющий обнаруживать эти ошибки при сборке, ну и обсуждаются мысли по реализации линтера шаблонов (для статического анализа биндингов и тд.). По сути все действия разработчиков с шаблонами были нацелены на упрощение анализа последних, правда целью было повысить эффективность кодогенерации для биндингов.
Отдельно меня лично радует возможность статического анализа шаблонов и тот факт, что при сборке они компилируются.
Также у меня плохие отношения с двухсторонним биндингом
В angular2 двустороннего биндинга нет, есть сахар для того что бы не писать постоянно проброс данных в обе стороны (иногда полезно, редко, но бывает).
С учетом того что теперь помимо ngModel есть ngFormModel, то необходимости в использовании двустороннего биндинга почти не остается. Только для очень простых случаев для которых подобные вещи выглядят оверхэдом.
{{foobar.test()}}
Если в test возникнет исключение, оно будет проглочено как в первой версии или всё же выведено в консоль?
Интуиция мне подсказывает, что ngFormModel — не серебряная пуля.
Если в test возникнет исключение, оно будет проглочено как в первой версии или всё же выведено в консоль?
выведет в консоль. Причем сначала ангуляр обернет исключение в свое (
EXCEPTION: Error during evaluation of "click"
), ну и выведет ORIGINAL EXCEPTION: Error: Your exception message
.что ngFormModel — не серебряная пуля.
нет конечно, не бывает универсальных решений. Но конкретно ngFormModel покрывает примерно 90% юзкейсов. Ну и можно расчитывать на то, что довольно скоро появятся форм билдеры на основе ngFormModel и т.д. Посмотрим, мне эта концепция нравится.
Да в общем-то и там и там не проглатывает:
1.х: plnkr.co/edit/POgFi6FHZk1cyhf75NgA?p=preview
2.х: plnkr.co/edit/sQdCcD2tPrtEt4rBFst4?p=preview
1.х: plnkr.co/edit/POgFi6FHZk1cyhf75NgA?p=preview
2.х: plnkr.co/edit/sQdCcD2tPrtEt4rBFst4?p=preview
Sign up to leave a comment.
Разбираемся с синтаксисом шаблонов в Angular2