Angular: Преобразуйте свои входные данные по желанию и просто
С самого начала Angular взаимодействие между родителями и дочерними элементами осуществляется с помощью аннотаций @Input()
и @Output()
.
@Input()
- это мощная аннотация, которая позволяет передавать данные из родительского компонента в дочерний компонент.
Одним из пожеланий сообщества было иметь возможность простым способом преобразовывать данные, передаваемые при вводе.
..И скоро это желание станет реальностью. Цель этой статьи - описать функцию, которая появится очень скоро, и привести вам несколько примеров использования.
Контекст
Давайте представим, что мы хотим преобразовать входные данные, которые принимают строку в качестве параметра, в логическое значение.
Это преобразование позволило бы нам написать
<app-expand expanded />
<app-expand expanded="true" />
<app-expand [expanded]="true" />
Чтобы иметь возможность записывать наши вызовы в дочерние компоненты таким образом, нам доступно несколько способов:
- метод получения и установки
- создать свою аннотацию
- свойство преобразования метатады аннотации
@Input()
(еще не выпущено)
Геттер и сеттер
@Component({ selector: 'app-expand' })
export class ExpandComponent {
#expand = false;
@Input() set expanded(value: string | boolean) {
this.#expand = value !== null &&
`${value}` !== 'false';
}
get expanded() {
return this.#expand;
}
}
Метод getter/setter является распространенным шаблоном в наших компонентах Angular.
В предыдущем фрагменте кода, когда разработчик устанавливает расширенные входные данные, выполняется код установки и выполняется преобразование.
В этом преобразовании я не проверяю, является ли переданное значение неопределенным, чтобы разрешить следующую запись HTML.
<app-expand expanded />
Этого решения может быть достаточно, но есть очень большая проблема.
Как правило, компонент имеет несколько входов, и если каждый вход требует преобразования, компонент может расти с очень небольшой добавленной стоимостью.
Более приятным и долговечным решением в будущем было бы создание собственного декоратора.
Создайте свой собственный декоратор property
В javascript декоратор - это простая функция. В случае декоратора свойств он должен быть помещен перед свойством и описываться функцией, принимающей два параметра:
- цель
- ключ
Key (ключ) фактически представляет имя свойства
Target (цель) представляет функцию-конструктор класса для статического члена или прототип класса для члена-экземпляра.
Декоратор, преобразующий строковое значение в логическое значение, может быть следующим.
type SafeAny = any;
function toBoolean(value: string | boolean): boolean {
return value !== null && `${value}` !== 'false';
};
function InputBoolean(): (target: SafeAny,name: string) => void {
return function(target: SafeAny, name: string) {
let value = target[name];
Reflect.defineProperty(target, name, {
set(next: string) {
value = toBoolean(next);
},
get() {
return value;
},
enumerable: true,
configurable: true,
})
}
}
Этот декоратор позволяет нам централизовать логику преобразования и может использоваться в компоненте следующим образом:
@Component({ selector: 'app-expand' })
export class ExpandComponent {
@Input() @InputBoolean() expanded = false;
}
Почему бы не использовать @InputBoolean
отдельно без @Input
? Компилятору AOT необходимо, чтобы @Input
был видимым.
Этот метод создания декоратора элегантен и позволяет централизовать логику без ненужного шаблонного кода в компонентах.
Тем не менее, декораторы все еще являются экспериментальным понятием, и поначалу эту концепцию не всегда легко понять.
Вот почему Angular теперь позволяет нам использовать свойство простого преобразования в метаданных декоратора ввода для выполнения простых преобразований.
Новый способ преображения
Начиная с Angular 16 декоратор @Input
принимает метаданные в качестве параметра. Эта недавняя новинка была интегрирована в Angular, чтобы обеспечить необходимый ввод.
Вскоре эти метаданные также могут выполнять функцию преобразования.
function toBoolean(value: string | boolean): boolean {
return value !== null && `${value}` !== 'false';
};
@Component({ selector: 'app-expand' })
export class ExpandComponent {
@Input({ transform: toBoolean }) expanded = false;
}
очень легко не так ли? Преобразование выполняется с помощью простой функции, которая значительно увеличивает возможности разработчика.
Очевидно, что команда Angular не останавливается. Преобразование строки в логическое значение или строки в число довольно распространено. В этом смысле Angular предоставит нам вспомогательные функции, чтобы избежать перекодирования этой логики.
import { booleanAttribute, numberAttribute } from '@angular/core';
Встречаются случаи, когда мы желаем преобразовать значения входных данных, когда оно передается дочернему компоненту. Вы можете пройти по ссылке, чтобы узнать как добавить сверхспособности входным данным.