#angular #data-binding
#angular #привязка данных
Вопрос:
Допустим, у меня есть хранилище (большой одноэлементный объект), где я сохраняю общее состояние приложения. При необходимости это хранилище вводится в компоненты. Однако есть компоненты, которые используют только одно свойство из хранилища и используют его для условных выражений в своих шаблонах (конечно, только для чтения).
Есть ли здесь предпочтительная практика? Должен ли я использовать свойство непосредственно из встроенного хранилища
class MyComponent {
constructor(private store: Store) {}
}
// template
<div *ngIf="store.someFlag">...</div>
или я должен создать частное свойство в компоненте, а затем использовать его в шаблоне?
class MyComponent {
someFlag: boolean;
constructor(private store: Store) {
this.someFlag = store.someFlag;
}
}
// template
<div *ngIf="someFlag">...</div>
Меня больше всего беспокоит производительность — влияет ли доступ к данным из большого объекта в шаблоне на производительность циклов обнаружения угловых изменений?
Ответ №1:
Прежде всего, я предпочитаю использовать store.someFlag напрямую, поскольку это свойство может быть изменено, и оно будет немедленно отражено на странице, тогда как если вы назначите его локальной переменной, эта переменная не изменится со временем (если вы что-то не сделаете). Присвоение переменной имеет смысл, если вы планируете изменять это значение локально и не хотите, чтобы изменение распространялось обратно в хранилище. Я делаю это, когда хочу, чтобы дата моего приложения изначально применялась к этому экрану, но экран может изменить уже локальную дату обратно и принудительно по желанию пользователя.
И, во-вторых, если вы планируете использовать хранилище в шаблоне, убедитесь, что вы делаете его общедоступным в конструкторе (не частным), поскольку он не будет соответствовать более строгим правилам производства.
class MyComponent {
constructor(public store: Store) {}
}
Ответ №2:
Я хотел бы указать на другую проблему, которую я вижу в подходе: Вы привязываете компоненты к тому, как вы реализовали глобальное состояние. Делая это, вы тесно связываете их.
Допустим, вы хотите изменить структуру своего глобального состояния. Например, вы хотите переместить объект на один уровень ниже в иерархии состояния. При вашем подходе вам придется касаться каждого компонента, возможно, несколько раз для каждого компонента.
Я бы рекомендовал оставить компоненты как можно более глупыми. Дайте им реальный объект, который они могут прочитать или изменить как @Input()
. Пусть они работают над этим. Добавьте @Output()
, когда / если объект изменится.
Таким образом, вы более четко разделяете проблемы: компонентам просто нужно знать, как работать с одним конкретным классом, а не с общим состоянием.
Комментарии:
1. Но что, если мне понадобится это состояние примерно во всех компонентах, не станет ли утомительным и сложным поддерживать свойство /@Input и событие /@Output?
2. Если это «большой одноэлементный объект», как указано в вопросе, и вам нужен этот большой одноэлементный объект в каждом компоненте, я думаю, что что-то не так с архитектурой. В этом случае, да, это было бы утомительно и сложно, но это было бы просто указателем на проблему в другом месте.
3. Да, это правда, что для всех компонентов не требуется один и тот же «большой одноэлементный объект», но не для компонентов с уровнем иерархии более 3 . Существуют ли какие-либо другие возможные способы обмена данными на 4-5 уровень ниже по иерархии компонентов, кроме ввода / вывода?
4. Вы, конечно, можете предоставить своим компонентам большую часть своего состояния. Это всегда компромисс, когда вам нужно найти наилучший вариант для вашего конкретного варианта использования. Я бы просто избегал передачи одного и того же гигантского объекта состояния каждому компоненту и тем самым терял а) гибкость, б) тестируемость, в) обзор.
Ответ №3:
class MyComponent {
constructor(public store: Store) {}
}
// template
<div *ngIf="store.someFlag">...</div>
Это будет лучшим вариантом. Как если бы вы создали локальную копию этой переменной, то при обнаружении изменений может случиться так, что ваше значение при изменении из другого модуля / компонента не будет отражено в этом компоненте.