Есть ли разница между *ngTemplateOutlet и [ngTemplateOutlet] на самом деле?

Это не дубликат ответа этого поста и не (правильное) объяснение того, что делает оператор звездочки здесь. Однако он основан на них.

Суть в том, что *ngBeep — это удобный, синтаксически уверенный и краткий способ выражения [ngBeep]. Однако в своем коде я использовал следующие выражения. Они делают одно и то же (насколько я могу судить) и ведут себя так, как и ожидалось.

<div *ngFor = "let item of [1,2,3]">
  #{{item}}
  <ng-container *ngTemplateOutlet = "content"></ng-container>
  <ng-container [ngTemplateOutlet] = "content"></ng-container>
</div>

Ну... технически говоря, первое короче второго. Однако кажется глупым вводить совершенно новый оператор для удаления одного символа. Конечно, для других директив сохраненных символов/строк может быть гораздо больше, чем в приведенном выше конкретном примере.

Являются ли эти две контейнерные линии абсолютно эквивалентными (в данном патологическом случае)? Если нет, то чем они отличаются (под капотом)?

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
3
0
218
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Эти две строки в вопросе эквивалентны?

Да.

Однако звездный синтаксис-сахар — это нечто большее. Во-первых, он оборачивает свое содержимое в ng-template (потому что вам нужно визуализировать этот шаблон при каком-то условии или, возможно, несколько раз, в зависимости от директивы). Это означает следующий код.

<span *ngIf = "show">text</span>
// equivalent
<ng-template [ngIf] = "show"><span>text</span></ng-template>

Во-вторых, он добавляет префикс для передаваемых полей, как показано ниже.

<ng-container *ngTemplateOutlet = "content; context: {var1: 123}">
</ng-container>
// ...and its equivalent
<ng-container [ngTemplateOutlet] = "content" 
              [ngTemplateOutletContext] = "{var1: 123}">
</ng-container>

Затем она ссылается на данные, которые предоставляет сама директива, в контексте, что более удобно, вот так.

<li *ngFor = "let item of items; index as i; first as isFirst; trackBy: trackByFn">...</li>
// equivalent
<ng-template ngFor let-item [ngForOf] = "items" 
             let-i = "index" let-isFirst = "first"
             [ngForTrackBy] = "trackByFn">
  <li>...</li>
</ng-template>

Отличный ответ! Я взял на себя смелость отшлифовать его лингвистически — надеюсь, вы не против. Техническая сторона здесь идеальна, и я ясно понимаю, как мое недавнее невежество привело меня в замешательство. Спасибо друг.

Konrad Viltersten 13.04.2024 13:40

Нет... они не эквивалентны. Вы сами это объяснили. Я собирался понизить голос сразу после прочтения «Да». Но потом... Я все это прочитал, вы правы во всем своем ответе, за исключением той части «Да», которая меня сбивает с толку TL;DR. Правильные эквиваленты — это те, которые вы указали в своих примерах. Пожалуйста, просто исправьте первую часть своего ответа. В настоящее время в вашем ответе говорится: «Да, они эквивалентны, однако... нет, правильная эквивалентность - это все это...»

luiscla27 19.04.2024 02:49

Я бы сказал, что <ng-container *ngTemplateOutlet" это еще и сахар для <ng-template [ngTemplateOutlet]><ng-container>...

yurzui 20.04.2024 06:29
Ответ принят как подходящий

Как вы можете видеть в исходном коде, использование *ngTemplateOutlet и [ngTemplateOutlet] не отличается, поскольку вы используете один и тот же класс.
Глядя на класс, вы можете увидеть это свойство:

@Input() public ngTemplateOutletContext: C | null = null;

Это означает, что следующие фрагменты почти эквивалентны:

<ng-container *ngTemplateOutlet = "content; context: myContextObj">
</ng-container>
<ng-container [ngTemplateOutlet] = "content" 
              [ngTemplateOutletContext] = "myContextObj">
</ng-container>

Фактически, используя сокращение *, вы можете указать входные данные, если за Directive следует точка с запятой. Это справедливо для каждой структурной директивы : их можно использовать со ссылкой на свою selector или с структурной директивой *, сокращенно.

Что происходит под капотом, чтобы прежние фрагменты отличались?
Если вы посмотрите документацию, на которую я ссылаюсь, вы увидите, что при использовании сокращения * Angular обернет ваш элемент в ng-template и применит к нему директиву с селектором:
Из документации эти два шаблона эквивалентны:

<div class = "name" *ngIf = "hero">{{hero.name}}</div>
<ng-template [ngIf] = "hero">
  <div class = "name">{{hero.name}}</div>
</ng-template>

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

Возможно, это единственное различие между двумя подходами, которое может повлиять на опыт разработчика: если вы хотите использовать ngTemplateOutlet и другую структурную директиву, у вас есть 2 возможности:

  1. Оберните элемент в ng-container и используйте структурную директиву в двух разных элементах.
  2. Используйте только одно сокращение *
// Using 2 "*" shorthand in the same element: the code won't compile
<ng-container *ngTemplateOutlet = "content" *ngIf = "true">
</ng-container> 

// Approach 1, the code will compile
<ng-container *ngIf = "true">
  <ng-container *ngTemplateOutlet = "content">
  </ng-container>
</ng-container>

// Approach 2, the code will compile
<ng-container [ngTemplateOutlet] = "content" *ngIf = "true">
</ng-container>

Не могли бы вы подробнее рассказать о различных возможностях использования структурных директив?

Konrad Viltersten 13.04.2024 13:38

Конечно! Я понял, что вопрос не касается использования оператора *, сейчас я отредактировал ответ.

Igor Cantele 13.04.2024 14:23

Да, вы тоже правильно задали вопрос с первого раза. Я просто хотел некоторых подробностей, чтобы подтвердить, что я понял это полностью, а также «будущие поколения», видящие ответ, которые, возможно, находятся в еще большем замешательстве, чем я. Я уже принял другой ответ как ответ, но за большие усилия я поставлю вам +1 и также добавлю награду. Ты заслуживаешь это.

Konrad Viltersten 13.04.2024 14:32

Исправление в части вознаграждения. Кажется, я не могу. Нет кнопки, позволяющей создать округ (даже не сообщая мне, что он имеет право на это через определенный период времени). Может быть, это потому, что у меня уже есть один активный...? Не уверен.

Konrad Viltersten 13.04.2024 14:34

Спасибо! Думаю, нам придется подождать пару дней. «Баунти можно начать за вопрос через два дня после того, как вопрос был задан».. Если вы считаете, что этот ответ заслуживает видимости, я бы попросил вас проголосовать за него, если не пометить его как принятый ответ, чтобы он не потерял видимость для будущих читателей.

Igor Cantele 13.04.2024 17:19

Странно... Я получил электронное письмо, в котором говорилось: «Теперь вы сможете назначить награду, если хотите», но я не вижу этого нигде в вопросе. Есть ли у Stacky искусственный интеллект, который напоминает людям о необходимости выражать признательность на основе комментариев? Отличная функция, но все равно... чушь?! :D

Konrad Viltersten 17.04.2024 08:40

Комментарий написал с мобильного, возможно, я его по ошибке удалил, потому что тоже не вижу, извините :D

Igor Cantele 17.04.2024 09:02

Другие вопросы по теме