Pull to refresh

Comments 64

Простой и понятный обзор, спасибо за публикацию!
Спасибо за статью! а продолжение будет? было бы интересно прочитать про роутера.
На данный момент есть только angular/router, и я пока не нашел времени детально с ним разобраться. uiRouter 1.0 на подходе (и он намного лучше 0.x ветки) но судя по всему сразу angular2 они поддерживать не будут.

В целом различия в роутинге и подходах с оными было бы нелпохо освятить, я согласен. Тем более что хорошие статьи которые я встречал на данный момент слегка устарели в деталях.
UFO just landed and posted this here
На первый взгляд — да, это и побудило написать статью. Многие начинают рубить с плеча мол «ужас и кашмар». Да и я сам когда в первый раз увидел немного удивился. А разобравшись — не так страшно и есть свои плюсы. Вопросы реально возникают только с последним пунктом, так как выбор символа и способ применения не очевидны сразу.

Так же многие жалуются мол «зачем эти скобочки, почему нельзя было сделать это просто обычными атрибутами». Имеется в виду что если мы выбрали путь добавления префиксов/суффиксов то почему бы просто не сделать префикс 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".

> сразу видно где биндинги

Более того, сразу видно, где привязки одностороние, а где — двусторонние, а где их вообще нет. В первом ангуляре эту разницу увидеть труднее.

Дополнил статью, это на самом деле важный аспект.
А можно было бы наглядней:
input 
    .type : =text
    .disabled < isDisabled
    .placeholder : =Some Field
    .value < modelValue
    .required : true
    .maxLength : 12
Это наглядно для вас. Для непосвещенного человека это целый сэт новых вещей.
А ангуляровские скобочки и звёздочки — это не сет новых вещей?
нет, потому что вы можете не пользоваться ими. Это просто сахар. Я чуть обновил текст статьи и добавил информацию об этом а так же почему именно такие скобочки были взяты за основу.

В вашем примере например не понятно в чем разница между
.disabled < isDisabled

и
.placeholder : =Some Field


По идее же должно быть одно и то же, нет? Сначала я подумал что одно это биндинг (по аналогии с редиректом в bash) а другое — просто значение, но тогда последние два свойства не согласуются.

А в angular2 запись
<div [inner-html]="expression"></div>


намекает нам о

div['innerHtml'] = expression();
«bindon-ngModel=» — выглядит ещё более странно, чем с сахаром.

Разница в том, что стрелочка показывает откуда куда перемещается значение (биндинг, да), а двоеточие задаёт значение по умолчанию.

.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 минут объяснить, при этом он позволяет полностью описывать компоненты (без поведения, конечно). А сколько потребуется времени, чтобы объяснить верстальщику как создавать директивы в ангуляре, как работают скоупы, почему в именах свойств всегда должна быть точечка?
стати, как Ангуляр2 вообще предлагает разруливать такие ситуации? Есть специальный синтаксис для установки стилей?

Из документации:
<div [style.width.px]="mySize">


для атрибутов можно так:
<div [attr.role]="myAriaRole">
.required : true

Это очень далеко от js. Похоже на мапу, но натыкаешься на "<" и такой wtf?!
А в ts ещё и мимикрирует под объявление типа, и по-невнимательности легко перепутать с
var required: boolean
Ну а это похоже на деструктивное присваивание:
[disabled]="isDisabled"


И что? Если бы тут хватало одного JS, то на JS бы и писали, а не выдумывали свои языки шаблонов.
деструктурированное присваивание — сильно зависит от контекста и будет смущать людей просто в JS. Вот честно пока вы не написали я бы даже не подумал об этом в таком ключе (как минимум потому что я против использования оного для переопределения значений переменных). То есть я привык именно к записи в контексте определения значения новых переменных.
Мне сложно вспомнить хтмл шаблонизатор без собственного синтаксиса. [disabled] хотя бы наглядное и по размерам больше, его легче увидеть, чем "<".
Не понимаю с чего бы свойства с биндингом должны быть более заметны, чем свойства без оного. Представьте, что в JS у нас был бы аналогичный синтасис:

// присваиваем констатну
foo = 123

// присваиваем значение переменной
[foo] = bar

Казалось бы, семантически отличаются лишь выражения справа, но синтаксически мы почему-то меняем выражение слева.
потому что тут не совсем так

foo = 123 // константа, обычное присвоение

[foo] = bar // интерпритируется как

watchFor('bar', () => foo = bar);


согласитесь, совершенно различная семантика присваивания. Первая запись говорит нам о простом присвоении, а вторая запись — о постоянном присвоении значения, мы гарантируем что foo всегда будет иметь значение bar. Аналог присвоения по ссылке, мы же имеем для этого обычно отдельную конструкцию:

foo &= bar;
Лучше бы оно интерпретировалось в:

@FRProp
get foo( ){ return 123 }

И:
@FRProp
get foo( ) { return this.bar }


Но всё это детали реализации, которые не должны влиять на апи.
ну оно по сути так и интерпритируется внутри. Только чуть сложнее.
Спасибо. Статья кардинально поменяла моё отношение к Angular2!

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»
Это все популистские лозунги. По факту же и там и там смесь HTML и JS.

Посмотрим на первый попавшийся пример компонента на ReactJS: пример. Что мы тут видим.

Собственно почти то же самое что мы бы увидели в Angular2 версии. Ну то есть опять же все в одном файлике, HTML с биндингами напрямую к свойствам DOM (то есть никаких специфичных вещей учить не надо почти). Серьезно, я реально не особо вижу разницы с концептуальной точки зрения. То что мы вместо прямой работы с виртуальным DOM должны использовать директивы как элементы декларативной разметки ангуляра — я считаю это плюсом, подобные вещи чуть проще тестировать. В целом же это единственное концептуальное различие. Но если сравнивать именно Angular2 и React — различия не большие и мне это нравится. Angular первой ветки действительно отстает от всего этого сильно.

По поводу высказывания — все верно. Потому что React кроме компонентов ничего более не предоставляет. Потому все остальное — исключительно забота разработчика. Ванила JS ему в руки. Хочет пусть с нуля все делает, хочет, пусть инфраструктуру готовую использует. Свобода.
UFO just landed and posted this here
Ребят, я сам из реактоводов, поэтому сильно ногами не пинайте. Недавно, в силу остоятельств, пришлось активно курить первый ангуляр и периодически, по мере продвижения по developer guide, у меня на заднице шевелились волосы. Честное слово!

Большинство этих моментов было связано с шаблонами (и самый ужасающий из них, это когда я читал про передачу параметров в колбэк директивы, отмеченный амперсандом) и поэтому, наткнувшись на эту статью, с любопытством ее открыл в надежде на лучшее.

Ну что я могу сказать: уже сильно лучше, но направление так и осталось неверное. Ну реально, ребят, неужели никому из вас не кажется, что *ngIf — это ужасающе адский костыль, а присутствие таких вот вещей как раз и говорит о фундаментальных архитектурных просчетах…
Если ngif — костыль, то что не костыль? Помесь кода и разметки? Вам это может быть и привычно, но на самом деле это выглядит странно. А ng-if это всего-лишь еще один аттрибут, чем он хуже value?
Я не про конкретно ngIf, а про дивную звездочку вначале, которая делает вообще черт знает что.
директивы, меняющие структуру DOM дерева, требуют того, что бы разработчики использовали элемент template. Вот и все. Что бы не писать

<template [ngIf]="expression">
  <span>Conditional HTML</span>
</template>


ввели звездочку, как синтаксический сахар.

<span *ngIf="expression">Conditional HTML</span>


вы можете не пользоваться звездочками, и иметь явную разметку. А можете пользоваться, и тогда можно будет быстро находить в темплейтах места, где происходит изменение subtree.
Ну, если не пользоваться * то вместо вот этого:

<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


Аргумент про разделение вёрстки и логики — мимо кассы?
Ну кому-то больше нравится собирать интерефейс из кусочков, разложенных по переменным:
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:
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-и, только их использовать надо так, чтобы читаемость не страдала. Хотить switch — запихните его в getColorInHex и все.
А я бы за тернарный оператор бил по рукам. Вариант приведенный в документации мне лично нравится больше.

Мне нравится подход 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


ну тут соглашусь, это компромис для достижения простой цели — UI как декларативная разметка. В React мы можем использовать все что захотим для формирования DOM (виртуального) а уж как оно в реальности будет рендриться не наша забота. А если ты хочешь сделать UI полностью декларативным, придется придумывать такие вот кастыли. И не могу сказать что это совсем уж что-то страшное.

Или еще один пример (о котором я писал выше) про передачу параметров в колбэк директивы


Тут уже попроще. Это не «коллбэк» директивы. Ну тоесть по сути это он родимый и есть, но не совсем так. Это выражение (опциональное обычно), которое имеет возможность запускать директива не теряя при этом изоляции. Ну то есть прямой аналог тут будет:

function link(scope, element, attrs) {
    scope.$apply(attrs.onClick);
}


А что до передачи в качестве аргументов объекта — это контекст, в котором выполняется выражение. Задача директивы, предоставить выражению контекст, содержащий данные. Это позволяет здорово изолировать систему и снизить связанность.

Выражения в angular это такой безопасный eval, контекстом которого мы можем управлять (eval это плохо не потому что динамически выполняется что-то, а потому что мы не можем управлять контекстом и ограничивать сайд эффекты).
В общем, когда ребята из двух лагерей подружатся и общими усилиями заменят ангуляроские шаблоны+фильтры+директивы+контроллеры реактом на моей улице наступит праздник))
на моей улице наступит праздник))


А я буду грустить. Я хочу что бы мой UI был полностью декларативен, что бы его можно было валидировать исключительно статическими анализаторами, а тестировать только логику обработки данных. Что бы я мог посадить любого верстальщика что бы он занимался исключительно стилями. Собственно поэтому я на реакт так и не перелез и не планирую.

А то что двум лагерям надо меньше враждовать и больше обсуждать схожие вещи и как можно улучшить дела — это да. Этого нехватает.
«Это же простая итерация по массиву объектов! Зачем она вообще?» — спросит реактовод.
«А затем, что иначе вы не сможете в значение option передать что-то кроме строки!»
«Ну, знаете ли...»

А как это будет выглядет в реакте?
просто добавляем элементы в цикле, ничего особо сложного.
В Angular тоже можем просто добавлять элементы в цикле, выбор то объекта вместо текстового значения как будет происходить?
Angular 2 не решил главную проблему — неконтролируемую связность директив\модулей, что по сути имеется в MV* архитектурах тоже. Даже опытные разработчики, смешивая директивы, используя scope и другую магию, вставляют новые «подпорки» для удовлетворения новых требований. Новый синтаксис лишь уменьшил возможность подобных манипуляций, но я чувствую, что Angular все еще испорчен.
неконтролируемую связность директив\модулей, что по сути имеется в MV* архитектурах тоже


Можете пояснить? Ибо я не особо понимаю о чем вы. Ибо никаких проблем с неконтролируемой связностью в angular2 нет, ну либо я уже отношусь к той категории людей которые не используют в ангуляре скоуп и «магию» со времен angular 1.2 и потому мне сложно понять о чем вы.
Angular 2 все еще поддерживает аттрибутивные директивы (а старый еще и классовые). В итоге можно было получить что-то типа
   <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 и т.д. Посмотрим, мне эта концепция нравится.
единственное что для 2.x ошибка теперь чуть более детализирована. Появляется информация о контексте ошибки, ну мол у какого элемента это и все такое.
Посыпаю голову пеплом, видимо не в ангуляре было дело.
Sign up to leave a comment.

Articles