Angular의 최신 버전 이후 프레임워크 내에서 새로운 기본 반응성 시스템인 신호가 개발되었습니다!
오늘 돌이켜보면 특정 사용 사례가 다루어지지 않았음을 알게 되었으며 분명히 Angular 팀은 매우 적극적으로 대응하여 이러한 사용 사례를 다룰 수 있는 도우미를 제공할 것입니다.
이러한 사용 사례는 무엇입니까? 어떤 솔루션이 적용될 예정이며, 어떻게 사용될 예정인가요?
이 문제를 설명하는 것부터 시작하겠습니다.
특정 수량의 과일 바구니가 있다고 가정해 보겠습니다.
수량은 과일을 입력하는 컴포넌트로 관리됩니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); count = signal(1); updateQuantity(): void { this.count.update(prevCount => prevCount++); } }
입력된 과일 가격이 변경되면 변수를 재설정해야 합니다.
간단한 해결책은 효과를 사용하는 것입니다
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); quantity = signal(1); countEffect(() => { this.fruit(); this.quantity.set(1); }, { allowSignalWrites: true }) updateQuantity(): void { this.quantity.update(prevCount => prevCount++); } }
앞의 코드는 나쁜 습관입니다. 이것이 왜 중요한 질문인가요?
신호 수량을 설정하려면 signalWrites 옵션을 true로 설정해야 합니다. 이는 주어진 문제에 대한 잘못된 해석으로 인한 것입니다.
우리의 경우, 구현 시 동기화되지 않은 두 변수를 동기화하려고 합니다
카운터는 우리의 초기 소스인 과일과 독립적이지 않습니다. 실제로 여기에는 초기 소스가 과일이고 나머지는 과일의 파생물인 구성 요소 상태가 있습니다.
다음과 같이 문제를 구체화
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{fruitState().quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); fruitState = computed(() => ({ source: fruit(), quantity: signal(1), })); updateQuantity(): void { this.fruitState().quantity.update(prevCount => prevCount++); } }
이러한 구체화는 과일의 수량과 강력하게 연결됩니다.
따라서 과일이 변경되자마자 계산된 변수인 FruitState가 자동으로 다시 계산됩니다. 이 재계산은 1로 초기화된 신호인 수량 속성을 가진 객체를 반환합니다.
신호를 반환하면 클릭 시 변수가 증가하고 과일이 변경되면 간단히 재설정될 수 있습니다.
비교적 간단한 패턴 설정인데 단순화할 수는 없을까요?
Angular 19의 등장으로 파생 신호를 계산하는 새로운 기능이 등장했습니다.
지금까지는 계산된 함수가 있었지만 이 함수는 수량 변수에 대한 이전 사용 사례에서 실용적이었을 WrittableSignal이 아닌 신호를 반환했습니다.
여기서 LinkedSignal이 등장합니다. LinkedSignal은 이름에서 알 수 있듯이 두 신호를 강력하게 연결할 수 있습니다.
이전 사례로 돌아가면 이 함수를 사용하면 다음과 같이 코드를 단순화할 수 있습니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); quantity = linkedSignal({ source: fruit, computation: () => 1 }); updateQuantity(): void { this.quantity.update(prevCount => prevCount++); } }
linkedSignal 함수는 다음과 같이 정의됩니다.
linkedSignal(computation: () => D, options?: { equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>; linkedSignal(options: { source: () => S; computation: (source: NoInfer<S>, previous?: { source: NoInfer<S>; value: NoInfer<D>; }) => D; equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;
첫 번째 정의인 "약식" 정의에서 linkedSignal 함수는 계산 함수를 매개변수 및 구성 개체로 사용합니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); count = signal(1); updateQuantity(): void { this.count.update(prevCount => prevCount++); } }
이전 예에서는 계산 기능이 시갈 수량에 따라 달라지므로 수량 변경 시 계산 기능이 재평가됩니다.
두 번째 정의에서 linkedFunction 메소드는 객체를 세 가지 속성이 있는 매개변수로 사용합니다
"축약된" 계산 함수와 달리 여기서 계산 함수는 소스 값과 "선례"를 매개변수로 사용합니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); quantity = signal(1); countEffect(() => { this.fruit(); this.quantity.set(1); }, { allowSignalWrites: true }) updateQuantity(): void { this.quantity.update(prevCount => prevCount++); } }
Angular 19에서는 간단한 데이터 가져오기 및 쿼리 상태(보류 중 등), 데이터 및 오류 검색을 위한 새로운 API를 도입할 예정입니다.
프레임워크에 어느 정도 익숙한 사람들을 위해 이 새로운 API는 useRessource 후크와 약간 유사하게 작동합니다.
예를 살펴보겠습니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{fruitState().quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); fruitState = computed(() => ({ source: fruit(), quantity: signal(1), })); updateQuantity(): void { this.fruitState().quantity.update(prevCount => prevCount++); } }
이 코드 조각에 대해 알아야 할 몇 가지 사항이 있습니다
이 스니펫 코드에는 몇 가지 참고할 사항이 있습니다.
다음 효과는 해당 값을 인쇄합니다
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); quantity = linkedSignal({ source: fruit, computation: () => 1 }); updateQuantity(): void { this.quantity.update(prevCount => prevCount++); } }
위에서 설명한 대로 기본적으로 FruitId 신호는 추적되지 않습니다.
그러면 이 신호 값이 변경될 때마다 http 요청을 어떻게 다시 시작합니까? 또한 FruitId 신호 값이 변경되고 이전 요청에 대한 응답이 변경되지 않은 경우 이전 요청을 취소하는 방법도 있습니다. 도착?
리소스 함수는 request라는 또 다른 속성을 사용합니다.
이 속성은 신호에 의존하는 함수를 값으로 취하고 그 값을 반환합니다.
linkedSignal(computation: () => D, options?: { equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>; linkedSignal(options: { source: () => S; computation: (source: NoInfer<S>, previous?: { source: NoInfer<S>; value: NoInfer<D>; }) => D; equal?: ValueEqualityFn<NoInfer<D>>; }): WritableSignal<D>;
위 코드에서 볼 수 있듯이 로더 함수는 두 개의 매개변수를 사용합니다
따라서 과일 세부 정보를 검색하는 httpRequest 중에 FruitId 신호 값이 변경되면 요청이 취소되고 새 요청이 시작됩니다.
마지막으로 Angular는 이 새로운 API를 RxJ와 결합하여 Rx 연산자의 이점을 활용할 수 있는 가능성도 고려했습니다.
리소스 함수와 정확히 동일한 방식으로 정의되는 rxResource 함수를 사용하여 상호 호환성을 달성합니다.
유일한 차이점은 관찰 가능
을 반환하는 로더 속성의 반환 유형입니다.
@Component({ template: `<button type="button" (click)="updateQuantity()"> {{quantity()}} </button>` }) export class QuantityComponent() { fruit = input.required<string>(); count = signal(1); updateQuantity(): void { this.count.update(prevCount => prevCount++); } }
여기에서는 abortSignal이 필요하지 않습니다. 과일 ID 변경 신호의 값이 rxResource 함수에 암시되어 있고 동작이 switchMap 연산자와 동일할 때 이전 요청을 취소합니다.
위 내용은 각도 반응성의 다음 개선 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!