Опираясь на мою предыдущую часть, в которой перечислены некоторые из моих первоначальных реакций на Angular 2 после перехода с проекта React, у меня есть некоторые мысли о том, как эти фреймворки внедряют разметку в DOM (или shadow-DOM) и эффекты .

Пример использования

Вот пример использования. У меня есть массив имен пользователей, которые я хочу отобразить, и я собираюсь отобразить их с помощью двух компонентов. Первый — это в основном <ul>, но здесь это умный компонент, который будет вручную извлекать данные (как и откуда не имеет значения). Дочерний компонент будет простым компонентом, в основном <li>, который просто отображает имя. Однако я буду использовать элементы <div>, чтобы для простоты уменьшить размер объявлений CSS.

// the data
const usernames = ["Donald", "Barack", "George", "William"]
// the basic markup structure
<div class="list">
  <div class="item">Donald</div>
  <div class="item">Barack</div>
  <div class="item">George</div>
  <div class="item">William</div>
</div>
// the basic styles
.list {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.item {
  flex: 0 0 25%;
}

Реагировать

Базовая реализация React будет выглядеть так:

const Item = ({name}) => <div style={{'flex': '0 0 25%'}}>{name}</div>
class List extends Component {
  render(){
    const usernames = ["Donald", "Barack", "George", "William"]
    const listStyle = {
      'display': 'flex',
      'flex-direction': 'row',
      'flex-wrap': 'wrap'
    }
    return (
      <div style={listStyle}>
        {usernames.map(item => <Item name={item} />)}
      </div>
    )
  }
}

Результирующая разметка будет точно соответствовать ожидаемой разметке (за исключением объявлений стилей вместо классов CSS), потому что React полностью заменяет дочерние компоненты структурой, возвращаемой return() подкомпонента.

Очень просто.

Угловой 2

Объяснить, как Angular 2 справляется с этим, будет сложнее. Во-первых, мне придется включить оба компонента в содержащий их модуль, что я здесь не демонстрирую. Я также исключаю проверки TypeScript.

Во-первых, смарт-компонент.

@Component({
  selector: 'my-list',
  template: `
    <style>
      .list { 
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
      }
    </style>
    <div class="list">
      <my-item *ngFor="let item of items" [name]="item"></my-item>
    </div>
  `
})
export class ListComponent {
  items = ["Donald", "Barack", "George", "William"];
  constructor(){ }
}

И тупой.

@Component({
  selector: 'my-item',
  template: `
    <style>
      .item { 
        flex: 0 0 25%;
      }
    </style>
    <div class="item">{{name}}</div>
  `
})
export class ItemComponent {
  @Input() name: string;
  constructor(){ }
}

Результирующая разметка (в Chrome Inspector) будет выглядеть так:

<project-card-list>
  <div class="list">
    <my-item>
      <div class="item">Donald</div>
    <my-item>
    <my-item>
      <div class="item">Barack</div>
    <my-item>
    <my-item>
      <div class="item">George</div>
    <my-item>
    <my-item>
      <div class="item">William</div>
    <my-item>
  </div>
</project-card-list>

Как видите, подкомпонент заключен в тег, соответствующий его селектору. Меня это беспокоит по нескольким причинам:

  1. Макет flex-box кажется, по-прежнему работает, даже несмотря на наличие промежуточного тега. Я понятия не имею, почему именно (странность теневого DOM?). О том, как я ожидаю, что это будет работать, см. в этом JSBin. С одной стороны, это, вероятно, уместно, потому что это то, что я имел в виду, но с другой стороны, я не могу понять, почему тег <my-item>, похоже, игнорируется при расчете макета, и я не могу найти никакой документации по этому поводу. Если я установлю my-itemtag на display: flex, он сломается, но не иначе. Кто-нибудь может это объяснить?
  2. Как и все остальное в Angular и React — код всегда кажется в два раза более многословным, и я ненавижу, ненавижу, ненавижу этот синтаксис: *ngFor="let item of items" по сравнению с чистым .map() React.
  3. Есть и другие странности, с которыми вы можете столкнуться, если избавитесь от оболочки, содержащей <div class="item">, в дочернем компоненте и попытаетесь напрямую стилизовать тег my-item. Во-первых, этот класс не будет затронут каким-либо CSS, который вы укажете в дочернем компоненте, и хотя я думаю, что вы можете перейти вверх по цепочке областей видимости (может быть, :host?), это кажется действительно уродливым и похоже на то, чего лучше избегать. .