Найдено несколько директив host: Найдено несколько директив host – QA PR-CY

Как nginx обрабатывает запросы

Как предотвратить обработку запросов без имени сервера
Определение виртуального сервера по имени и IP-адресу
Конфигурация простого сайта PHP
Определение виртуального сервера по имени

nginx вначале решает, какой из серверов должен обработать запрос. Рассмотрим простую конфигурацию, где все три виртуальных сервера слушают на порту *:80:

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      80;
    server_name example.com www.example.com;
    ...
}

В этой конфигурации, чтобы определить, какому серверу следует направить запрос, nginx проверяет только поле “Host” заголовка запроса. Если его значение не соответствует ни одному из имён серверов или в заголовке запроса нет этого поля вовсе, nginx направит запрос в сервер по умолчанию для этого порта. В вышеприведённой конфигурации сервером по умолчанию будет первый сервер, что соответствует стандартному поведению nginx по умолчанию. Сервер по умолчанию можно задать явно с помощью параметра

default_server в директиве listen:

server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}
Параметр default_server появился в версии 0.8.21. В более ранних версиях вместо него следует использовать параметр default.

Следует иметь в виду, что сервер по умолчанию является свойством слушающего порта, а не имени сервера. Подробнее это обсуждается ниже.

Как предотвратить обработку запросов без имени сервера

Если запросы без поля “Host” в заголовке не должны обрабатываться, можно определить сервер, который будет их отклонять:

server {
    listen      80;
    server_name "";
    return      444;
}

Здесь в качестве имени сервера указана пустая строка, которая соответствует запросам без поля “Host” в заголовке, и возвращается специальный для nginx код 444, который закрывает соединение.

Начиная с версии 0.8.48 настройка server_name "" является стандартной и может явно не указываться. В более ранних версиях в качестве стандартного имени сервера выступало имя машины (hostname).
Определение виртуального сервера по имени и IP-адресу

Рассмотрим более сложную конфигурацию, в которой некоторые виртуальные серверы слушают на разных адресах:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

В этой конфигурации nginx вначале сопоставляет IP-адрес и порт запроса с директивами listen в блоках server. Затем он сопоставляет значение поля “Host” заголовка запроса с директивами server_name в блоках server, которые соответствуют IP-адресу и порту.

Если имя сервера не найдено, запрос будет обработан в сервере по умолчанию. Например, запрос www.example.com, пришедший на порт 192.168.1.1:80, будет обработан сервером по умолчанию для порта 192.168.1.1:80, т.е. первым сервером, т.к. для этого порта www.example.com не указан в списке имён серверов.

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

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}
Конфигурация простого сайта PHP

Теперь посмотрим на то, как nginx выбирает location для обработки запроса на примере обычного простого PHP-сайта:

server {
    listen      80;
    server_name example. org www.example.org;
    root        /data/www;
    location / {
        index   index.html index.php;
    }
    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }
    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

nginx вначале ищет среди всех префиксных location’ов, заданных строками, максимально совпадающий. В вышеприведённой конфигурации указан только один префиксный location “/”, и поскольку он подходит под любой запрос, он и будет использован, если других совпадений не будет найдено. Затем nginx проверяет location’ы, заданные регулярными выражениями, в порядке их следования в конфигурационном файле. При первом же совпадении поиск прекращается и nginx использует совпавший location. Если запросу не соответствует ни одно из регулярных выражений, nginx использует максимально совпавший префиксный location, найденный ранее.

Следует иметь в виду, что location’ы всех типов сопоставляются только с URI-частью строки запроса без аргументов. Так делается потому, что аргументы в строке запроса могут быть заданы различными способами, например:

/index.php?user=john&page=1
/index.php?page=1&user=john

Кроме того, в строке запроса можно запросить что угодно:

/index.php?page=1&something+else&user=john

Теперь посмотрим, как бы обрабатывались запросы в вышеприведённой конфигурации:

  • Запросу “/logo.gif” во-первых соответствует префиксный location “/”, а во-вторых — регулярное выражение “\.(gif|jpg|png)$”, поэтому он обрабатывается location’ом регулярного выражения. Согласно директиве “root /data/www” запрос отображается в файл /data/www/logo.gif, который и посылается клиенту.
  • Запросу “/index.php” также во-первых соответствует префиксный location “/”, а во-вторых — регулярное выражение “\. (php)$”. Следовательно, он обрабатывается location’ом регулярного выражения и запрос передаётся FastCGI-серверу, слушающему на localhost:9000. Директива fastcgi_param устанавливает FastCGI-параметр SCRIPT_FILENAME в “/data/www/index.php”, и сервер FastCGI выполняет указанный файл. Переменная
    $document_root
    равна значению директивы root, а переменная $fastcgi_script_name равна URI запроса, т.е. “/index.php”.
  • Запросу “/about.html” соответствует только префиксный location “/”, поэтому запрос обрабатывается в нём. Согласно директиве “root /data/www” запрос отображается в файл /data/www/about.html, который и посылается клиенту.
  • Обработка запроса “/” более сложная. Ему соответствует только префиксный location “/”, поэтому запрос обрабатывается в нём. Затем директива index проверяет существование индексных файлов согласно своих параметров и директиве “root /data/www”. Если файл /data/www/index.html не существует, а файл /data/www/index.php существует, то директива делает внутреннее перенаправление на “
    /index.php
    ” и nginx снова сопоставляет его с location’ами, как если бы такой запрос был послан клиентом. Как мы видели ранее, перенаправленный запрос будет в конечном итоге обработан сервером FastCGI.
автор: Игорь Сысоев
редактор: Brian Mercer

Имена сервера

Имена с масками
Имена, заданные регулярными выражениями
Прочие имена
Интернационализованные имена
Выбор виртуального сервера
Оптимизация
Совместимость

Имена сервера задаются с помощью директивы server_name и определяют, в каком блоке server будет обрабатываться тот или иной запрос. См. также “Как nginx обрабатывает запросы”. Имена могут быть заданы точно, с помощью маски или регулярного выражения:

server {
    listen       80;
    server_name  example. (www\.)?(
?<domain>
.+)$; location / { root /sites/$domain; } }

Библиотека PCRE поддерживает именованные выделения, используя следующий синтаксис:

?<name>Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0
?'name'Совместимый с Perl 5.10 синтаксис, поддерживается начиная с PCRE-7.0
?P<name>Python-совместимый синтаксис, поддерживается начиная с PCRE-4.0
Если nginx отказывается запускаться и выдаёт сообщение об ошибке:

pcre_compile() failed: unrecognized character after (?< in ...

то это значит, что используется старая версия библиотеки PCRE и следует вместо этого попробовать синтаксис “?P<name>”.

(www\.)?(.+)$; location / { root /sites/$2; } }

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

Прочие имена

Некоторые имена имеют специальное значение.

Если необходимо обрабатывать запросы без поля “Host” в заголовке в блоке server, который не является сервером по умолчанию, следует указать пустое имя:

server {
    listen       80;
    server_name  example.org  www.example.org  "";
    ...
}

Если директива server_name не задана в блоке server, то nginx будет использовать пустое имя в качестве имени сервера.

Версии nginx вплоть до 0.8.48 в этом случае использовали имя хоста (hostname) машины в качестве имени сервера.

Если имя сервера задано как “$hostname

” (0.9.4), то используется имя хоста (hostname) машины.

Если в запросе вместо имени сервера указан IP-адрес, то поле “Host” заголовка запроса будет содержать IP-адрес, и запрос можно обработать, используя IP-адрес как имя сервера:

server {
    listen       80;
    server_name  example.org
                 www.example.org
                 ""
                 192.168.1.1
                 ;
    ...
}

В примерах конфигурации серверов, обрабатывающих все запросы, встречается странное имя “_”:

server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

Оно не является каким-то особенным, это просто одно из множества некорректных доменных имён, которые никогда не пересекутся ни с одним из реальных имён. С тем же успехом можно использовать имена типа “--” и “!@#”.

Версии nginx вплоть до 0.6.25 поддерживали специальное имя “*”, которое многими неверно воспринималось как имя сервера для обработки всех запросов. Оно никогда так не работало, и не работало как имя с маской. Это имя действовало так же, как сейчас действует директива server_name_in_redirect. Специальное имя “*” объявлено устаревшим, а вместо него следует использовать директиву server_name_in_redirect. Заметьте, что с помощью директивы server_name нельзя задать ни имя сервера для обработки всех запросов, ни сервер по умолчанию. Это является свойством директивы listen, а не server_name. См. также “Как nginx обрабатывает запросы”. Можно настроить серверы, слушающие на портах *:80 и *:8080, и указать, что один из них будет сервером по умолчанию для порта *:8080, а другой — для порта *:80:

server {
    listen       80;
    listen       8080  default_server;
    server_name  example.net;
    ...
}
server {
    listen       80  default_server;
    listen       8080;
    server_name  example.org;
    ...
}
Интернационализованные имена

Для указания интернационализированных доменных имён (IDNs) в директиве server_name следует указывать Punycode-представление имени:

server {
    listen       80;
    server_name  xn--e1afmkfd. xn--80akhbyknj4f;  # пример.испытание
    ...
}
Выбор виртуального сервера

Сначала соединение создаётся в контесте сервера по умолчанию. Затем имя сервера может быть определено на следующих стадиях обработки запроса, каждая из которых участвует в выборе конфигурации:

  • предварительно во время операции SSL handshake согласно SNI

  • после обработки строки запроса

  • после обработки поля Host заголовка запроса

  • если после обработки строки запроса или поля Host заголовка запроса имя сервера не было выбрано, то nginx будет использовать пустое имя в качестве имени сервера.

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

  • в случае использования директивы ssl_protocols список протоколов задаётся библиотекой OpenSSL перед применением конфигурации сервера согласно имени, запрашиваемого через SNI. Таким образом, протоколы должны быть заданы только для сервера по умолчанию;
  • директивы client_header_buffer_size и merge_slashes задействуются перед чтением строки запроса, таким образом они используют конфигурацию сервера по умолчанию или конфигурацию сервера, выбранного через SNI;
  • в случае использования директив ignore_invalid_headers, large_client_header_buffers и underscores_in_headers, которые участвуют в обработке полей заголовка запроса, выбор сервера дополнительно зависит от того, была ли обновлена конфигурация сервера согласно строке запроса или полю заголовка Host;
  • ошибочный ответ будет обработан с помощью директивы error_page в том сервере, который в настоящий момент выполняет запрос.
Оптимизация

Точные имена, имена с масками, начинающиеся со звёздочки, и имена с масками, заканчивающиеся на звёздочку, хранятся в трёх хэш-таблицах, привязанных к слушающим портам. Размеры хэш-таблиц оптимизируются на фазе конфигурации таким образом, что имя может быть найдено с минимальным числом непопаданий в кэш процессора. Подробнее настройка хэш-таблиц обсуждается в отдельном документе.

В первую очередь имя ищется в хэш-таблице точных имён. Если имя не было найдено, то имя ищется в хэш-таблице имён с масками, начинающихся со звёздочки. Если и там поиск не дал результата, то имя ищется в хэш-таблице имён с масками, оканчивающихся на звёздочку.

Поиск в хэш-таблице имён с масками медленнее, чем поиск в хэш-таблице точных имён, поскольку имена сравниваются по доменным частям. Заметьте, что специальное имя с маской вида “.example.org” хранится в хэш-таблице имён с масками, а не в хэш-таблице точных имён.

Регулярные выражения проверяются последовательно, а значит являются самым медленным и плохо масштабируемым методом.

По вышеизложенным причинам предпочтительнее использовать точные имена, где это только возможно. Например, если к серверу наиболее часто обращаются по именам example.org и www.example.org, то эффективнее будет указать их явно:

server {
    listen       80;
    server_name  example. org  www.example.org  *.example.org;
    ...
}

нежели чем использовать упрощённую форму:

server {
    listen       80;
    server_name  .example.org;
    ...
}

Если задано большое число имён серверов, либо заданы необычно длинные имена, возможно потребуется скорректировать значения директив server_names_hash_max_size и server_names_hash_bucket_size на уровне http. Значение по умолчанию директивы server_names_hash_bucket_size может быть равно 32, 64, либо другой величине, в зависимости от размера строки кэша процессора. Если значение по умолчанию равно 32 и имя сервера задано как “too.long.server.name.example.org”, то nginx откажется запускаться и выдаст сообщение об ошибке:

could not build the server_names_hash,
you should increase server_names_hash_bucket_size: 32

В этом случае следует увеличить значение директивы до следующей степени двойки:

http {
    server_names_hash_bucket_size  64;
    . ..

Если задано большое число имён серверов, то будет выдано другое сообщение об ошибке:

could not build the server_names_hash,
you should increase either server_names_hash_max_size: 512
or server_names_hash_bucket_size: 32

В таком случае сначала следует попробовать установить server_names_hash_max_size в величину, близкую к числу имён серверов, и только если это не поможет или время запуска nginx станет неприемлемо большим, следует попытаться увеличить server_names_hash_bucket_size.

Если сервер является единственным сервером для слушающего порта, то nginx не будет проверять имена сервера вообще (а также не будет строить хэш-таблицы для слушающего порта). За одним исключением: если имя сервера задано регулярным выражением с выделениями, то nginx’у придётся выполнить это выражение, чтобы получить значения выделений.

Совместимость
  • Специальное имя сервера “$hostname” поддерживается начиная с версии 0. 9.4.
  • Имя сервера по умолчанию является пустой строкой “” начиная с версии 0.8.48.
  • Именованные выделения в именах серверов, заданных с помощью регулярных выражений, поддерживаются начиная с версии 0.8.25.
  • Выделения в именах серверов, заданных с помощью регулярных выражений, поддерживаются начиная с версии 0.7.40.
  • Пустое имя сервера “” поддерживается начиная с версии 0.7.12.
  • В качестве первого имени сервера можно задать маску или регулярное выражение начиная с версии 0.6.25.
  • Регулярные выражения в имени сервера поддерживаются начиная с версии 0.6.7.
  • Имена с маской вида example.* поддерживаются начиная с версии 0.6.0.
  • Специальная форма имени вида .example.org поддерживается начиная с версии 0.3.18.
  • Имена с маской вида *.example.org поддерживаются начиная с версии 0.1.13.
автор: Игорь Сысоев
редактор: Brian Mercer

angular — что такое host свойство в директивах и как узнать подробности

спросил

Изменено 3 года, 7 месяцев назад

Просмотрено 9к раз

Привет, я использую angular 8 с ng-bootstrap для добавления таблицы в свой проект
Я нашел этот код, который я не очень хорошо понял

 @Директива({
  селектор: 'th[сортируемый]',
  хозяин: {
    '[класс. asc]': 'направление === "asc"',
    '[class.desc]': 'direction === "desc"',
    '(щелкнуть)': 'повернуть()'
    }
  })
 

кто-нибудь может сказать мне, что говорит код?
и что означает «th» в селекторе.
также хост, могу ли я изменить его на что-то другое, потому что редактор сказал, что это старое свойство или что?
Всем спасибо

  • угловой
  • угловой8

Согласно документации Angular:

селектор

Селектор

: Селектор CSS, который идентифицирует эту директиву в шаблоне и запускает создание экземпляра директивы.

Итак, в вашем коде селектор: 'th[sortable]' селектор объявляет выбор по имени элемента th с атрибутом [sortable] . Вы должны найти что-то вроде ... в вашем html-файле.

ОБНОВЛЕНИЕ для ответа на комментарий : Согласно ссылке, опубликованной в комментарии, вот -й сортируемый в html-коде:

хост

Хост

: Сопоставляет свойства класса с привязками элементов хоста для свойств, атрибутов и событий, используя набор пар ключ-значение.

 хост: {
    [ключ: строка]: строка;
}
 

Предпочтительно использовать @HostBinding и @HostListener вместо host в соответствии с руководством по стилю angular, перейдите по этой ссылке для получения более подробной информации.

Чтобы заменить хост в вашем коде:

@HostBinding позволяет установить свойства элемента или компонента, в котором размещена директива. Таким образом, он заменит ваш код [class.asc] и [class.desc] следующим внутри вашей директивы :

 @HostBinding('class.asc') direction = 'asc';
@HostBinding('class.desc') direction = 'desc';
 

@HostListener позволяет прослушивать события в элементе или компоненте хоста. Итак, ваш '(клик)' 9Код 0038 будет заменен следующим кодом внутри вашей директивы :

 @HostListener('click') rotate() {
  // делать:
}
 
1

Во-первых, вы должны понять, в чем разница между директивой и компонентом .

В отличие от компонентов директивы не требуют представления. Они должны отвечать за логику рендеринга: добавление / удаление элементов и/или добавление пользовательского поведения к элементам или компонентам DOM.

th[sortable] — думайте об этом как о обычном CSS-селекторе . Это будет преобразовано в: Элемент th с атрибутом sortable : . Если бы селектор был разделен запятыми ( th,[sortable] ), это означало бы, что вы либо используете свою директиву как th , либо или <сортируемый> .

Свойство хоста , как указано в документации

Сопоставляет свойства класса с привязками элементов хоста для свойств, атрибутов и событий, используя набор пар ключ-значение.

, где хост-элемент — это элемент/компонент, к которому вы прикрепили свою директиву.

Однако вы можете добиться тех же результатов, используя HostBinding и HostListener .

Имея это в виду, ваш код может выглядеть так:

 @Directive({ ... })
класс экспорта YourAwesomeDirective {
 @HostBinding('класс.asc')
 получить ascClass () {
  вернуть this.direction === 'asc';
 }
 @HostBinding('класс.desc')
 получить descClass () {
  вернуть this.direction === 'описание';
 }
 @HostListener('щелчок', '[$event]')
 onClick (ev) { /* ... */ }
}
 

Зарегистрируйтесь или войдите в систему

Зарегистрируйтесь с помощью Google

Зарегистрироваться через Facebook

Зарегистрируйтесь, используя электронную почту и пароль

Опубликовать как гость

Электронная почта

Обязательно, но не отображается

Опубликовать как гость

Электронная почта

Требуется, но не отображается

Нажимая «Опубликовать свой ответ», вы соглашаетесь с нашими условиями обслуживания и подтверждаете, что прочитали и поняли нашу политику конфиденциальности и кодекс поведения.

Состав директивы Angular — эксперты Angular

Angular 15 уже на горизонте, а вместе с ним и множество замечательных функций. Одна из них, которая меня невероятно волнует, — это директивная композиция.

И не только я. Состав директив был одним из самых популярных вопросов Angular на GitHub. Давайте посмотрим, что это такое.

Чтобы объяснить состав директив, мы рассмотрим реальный вариант использования в виде цифровой доски объявлений. Мы хотим реализовать пинборд, который отображает булавки. Каждый пин должен отображать информационный текст в виде всплывающей подсказки при наведении. Кроме того, каждый штифт можно перетаскивать и первоначально вращать.

Цифровая доска с контактами

Код такого приложения может выглядеть примерно так.

 <пинборд>
  
  
  
  
  

 

У нас есть PinboardComponent , и мы проецируем на него кучу выводов. На этом этапе наши выводы будут отображаться, как показано на рисунке вверху. Это означает, что они еще не повернуты изначально, их нельзя перетаскивать, и мы не будем отображать всплывающую подсказку. Все функции, упомянутые выше, отсутствуют.

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

В нашем распоряжении есть DragableDirective , RotateDirective и TooltipDirective . Давайте используем эти директивы атрибутов, чтобы добавить недостающие функции к нашим булавкам.

 <пинборд #dragZone>
  <булавка
    повернуть = "45 градусов"
    tooltip="Отправлять новые продукты"
    перетаскиваемый
    [dragzone]="пинборд"
    изображение = "ракета"
  >
  
  <булавка
    повернуть = "-20 градусов"
    tooltip="Хорошее пиво после дня программирования"
    перетаскиваемый
    [dragzone]="пинборд"
    изображение = "пиво"
  >
  
  <булавка
    повернуть = "0 градусов"
    tooltip="Моя любимая клавиатура, Moonlander"
    перетаскиваемый
    [dragzone]="пинборд"
    изображение = "клавиатура"
  >
  
  <булавка
    повернуть = "10 градусов"
    tooltip="Создайте тесты для улучшения кода"
    перетаскиваемый
    [dragzone]="пинборд"
    изображение = "тестирование"
  >
  
  <булавка
    повернуть = "25 градусов"
    tooltip="Нет кофе, нет кода"
    перетаскиваемый
    [dragzone]="пинборд"
    изображение = "кофе"
  >
  

 

Каждый штифт теперь применяет директиву атрибута rotate и передает заданные начальные градусы поворота. Затем есть директива атрибута tooltip с текстом всплывающей подсказки и, что не менее важно, перетаскиваемый атрибут с дополнительным вводом dragZone .

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

Ницца. Это хороший подход, но он имеет некоторые недостатки.

Для завершения функции PinComponent ; разработчик должен помнить, какие директивы нужны, и применять все директивы самостоятельно.

Было бы здорово, если бы мы могли предоставить PinComponent функции перетаскивания, всплывающей подсказки и поворота прямо из коробки и при этом повторно использовать наши директивы?

Зачем нужна композиция директив?

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

 класс экспорта PinComponent расширяет реализацию DragableDirective OnInit {}
 

Приятно то, что, используя наследование, мы можем наследовать все функции Angular, такие как HostBinding или HostListeners и т. д.…. И это также очень хорошо работает с проверкой типов шаблонов и минификаторами.

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

Кроме того, у нас нет возможности сузить общедоступный API PinComponent . Публичный API директив просачивается в производные классы.

Это не оптимальное решение, поэтому сейчас мы получаем композицию директив.

Подпишитесь на меня в Твиттере, потому что вы будете получать уведомления о новых сообщениях в блоге Angular и интересных материалах внешнего интерфейса!😉

Состав директив

Новый API составления директив представляет hostDirectives в декораторе компонентов и директив.

Значением свойства является массив объектов конфигурации. Каждый объект конфигурации содержит обязательный атрибут директивы и два необязательных свойства , ввод и , вывод .

 hostDirectives?: (Тип <неизвестно> | {
  директива: Тип<неизвестно>;
  входы?: строка [];
  выходы?: строка [];
})[];
 

Давайте продолжим и попробуем использовать это совершенно новое свойство в нашем PinComponent , чтобы добавить всплывающую подсказку, поворот и функции перетаскивания.

 @Компонент({
  селектор: 'булавка',
  шаблон: ``,
  директивы хоста: [
    {директива: TooltipDirective},
    {директива: DragableDirective},
    {директива: RotateDirective},
  ],
})
класс экспорта PinComponent реализует OnInit {}
 

С помощью этого мы также можем удалить директиву атрибута draggable из контактов в нашем HTML.

 <штифт
  повернуть = "25 градусов"
  tooltip="Нет кофе, нет кода"
  [dragzone]="пинборд"
  изображение = "кофе"
>

 

Если бы нам не нужно было передавать всплывающую подсказку и вращать ввод , мы могли бы также удалить эти атрибуты, поскольку теперь они предоставляются hostDirectives на PinComponent . Но нам по-прежнему нужны эти атрибуты, а также атрибут dragzone , потому что эти атрибуты являются входными данными.

Давайте запустим наше приложение. Вместо отличных фич получаем кучу ошибок компиляции:

 ERROR
src/app/pin.component.ts:20:17 - ошибка NG2014:
Директива хоста TooltipDirective должна быть автономной 20
{директива: TooltipDirective}
 

Что ж, это понятное сообщение об ошибке, которое информирует нас об одном из ограничений директив хоста.

Директивы хоста можно использовать только с автономными директивами. Без проблем. Давайте продолжим и преобразуем наши директивы в автономные директивы.

Автономный режим, что это? Автономные компоненты были представлены в качестве предварительного просмотра для разработчиков в Angular 14. Если вы хотите узнать больше об этом, ознакомьтесь с моей статьей об автономных компонентах. Отдельные компоненты Angular

Чтобы преобразовать наши директивы в автономные директивы, мы должны добавить свойство standalone со значением true в декораторе директив и переместить их из массива объявлений в массив импортов в AppModule .

Отлично, попробуем!

Состояние наведения PinComponent со сломанной всплывающей подсказкой. Директива всплывающей подсказки выполняется, но текст всплывающей подсказки не определен.

Всплывающая подсказка ломается при наведении, значок не поворачивается, а булавку нельзя перетаскивать. Почему это? Похоже, что ввод директив больше не работает. Но почему? мы по-прежнему передаем их в HTML как атрибуты компонента булавки!

Всякий раз, когда вы используете hostDirectives, все входы и выходы по умолчанию скрыты. Мы явно должны предоставить общедоступный API для входов и выходов объектов конфигурации.

 директивы хоста: [
  { директива: TooltipDirective, входы: ['tooltip'] },
  {директива: DragableDirective, входы: ['dragzone'] },
  {директива: RotateDirective, входы: ['rotate'] },
];
 

Это отличная функция, поскольку она дает нам полный контроль над общедоступным API нашего компонента. Запустим наш код.

Повернутый и наведенный PinComponent отображает текст всплывающей подсказки и может быть изменен с помощью перетаскивания.

Отлично, мы получаем всплывающую подсказку при наведении, мы получаем вращение, и, конечно же, пины можно перетаскивать. Все функции вроде работают. Как насчет выводит свойство ?

Точно так же, как мы настроили наши входы, мы также можем настроить наши выходы. Наш DragableDirective , например, генерирует событие, которое уведомляет вас, когда вы захватываете пин. Мы можем использовать свойство outputs, чтобы включить событие pinGrabbed в нашем общедоступном API.

 директивы хоста: [
  { директива: TooltipDirective, входы: ['tooltip'] },
  {
    директива: DragableDirective,
    входы: ['зона перетаскивания'],
    выходы: ['pinGrabbed'],
  },
  {директива: RotateDirective, входы: ['rotate'] },
];
 

Довольно интересно, правда? Но это не все; есть даже больше.

Псевдонимы

Еще одна полезная функция композиции директив — псевдонимы входных и выходных данных. dragzone — довольно общее название для нашего входа. В контексте пинов было бы точнее назвать Вход pinBoard вместо dragzone .

Воспользуемся синтаксисом псевдонима для переименования свойства dragzone в DragableDirective .

 директивы хоста: [
  // ...
  {
    директива: DragableDirective,
    входы: ['dragzone: pinBoard'],
    выходы: ['pinGrabbed'],
  },
  // ...
];
 

Отлично. После присвоения псевдонима мы можем использовать вход pinBoard на выводе.

 <штифт
  повернуть = "0 градусов"
  tooltip="Моя любимая клавиатура, Moonlander"
  [pinBoard]="доска"
  изображение = "клавиатура"
  (pinGrabbed)="pinGrabbed()"
>

 

Псевдоним работает точно так же для выходов .

Сводка

Композиция директив — это уникальная и захватывающая функция, предлагающая следующие преимущества.

  • Мы можем применить к хосту столько директив, сколько захотим. Ограничений нет.

  • По умолчанию все Входы и Выходы скрыты. Мы можем использовать свойства inputs и outputs , чтобы включить их в наш общедоступный API и сделать их видимыми.

  • Состав директив работает с проверкой типа шаблона.

  • Все функции директив, такие как HostBinding , маркеры внедрения и т.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *