Primero aprendí Vue.js y ahora tengo un proyecto en Angular 4, así que acabo de aprender Angular. Encuentro que no todo es tan diferente de Vue, excepto la "Propiedad calculada". En Vue, puedo crear una propiedad calculada que escucha los cambios de otras propiedades y ejecuta los cálculos automáticamente.
Por ejemplo (en Vue 2):
computed: { name(){ return this.firstname + ' ' + this.lastname; } }La propiedad de nombre solo se volverá a calcular cuando cambie el nombre o el apellido. ¿Cómo manejar esto en Angular 2 o 4?
Si bien esto ya está respondido, creo que no es una muy buena respuesta y los usuarios no deberían usar captadores como propiedades calculadas en angular. ¿Por qué puedes preguntar? getter es solo sintaxis de azúcar para la función y se compilará para una función simple, lo que significa que se ejecutará en cada verificación de detección de cambios. Esto es terrible para el rendimiento porque la propiedad se vuelve a calcular cientos de veces en cualquier cambio.
Eche un vistazo a este ejemplo: https://plnkr.co/edit/TQMQFb?p=preview
@Component({ selector: 'cities-page', template: ` <label>Angular computed properties are bad</label> <ng-select [items]="cities" bindLabel="name" bindValue="id" placeholder="Select city" [(ngModel)]="selectedCityId"> </ng-select> <p *ngIf="hasSelectedCity"> Selected city ID: {{selectedCityId}} </p> <p><b>hasSelectedCity</b> is recomputed <b [ngStyle]="{'font-size': calls + 'px'}">{{calls}}</b> times</p> ` }) export class CitiesPageComponent { cities: NgOption[] = [ {id: 1, name: 'Vilnius'}, {id: 2, name: 'Kaunas'}, {id: 3, name: 'Pabradė'} ]; selectedCityId: any; calls = 0; get hasSelectedCity() { console.log('hasSelectedCity is called', this.calls); this.calls++; return !!this.selectedCityId; } }Si realmente desea tener propiedades calculadas, puede usar un contenedor de estado como mobx
class TodoList { @observable todos = []; @computed get unfinishedTodoCount() { return this.todos.filter(todo => !todo.finished).length; } }mobx tiene un decorador @computed, por lo que la propiedad getter se almacenará en caché y se recalculará solo cuando sea necesario
Intentaré mejorar el de Andzej Maciusovic con la esperanza de obtener una respuesta canónica. De hecho, VueJS tiene una función llamada propiedad calculada que se puede mostrar rápidamente con un ejemplo:
<template> <div> <p>A = <input type="number" v-model="a"/></p> <p>B = <input type="number" v-model="b"/></p> <p>C = <input type="number" v-model="c"/></p> <p>Computed property result: {{ product }}</p> <p>Function result: {{ productFunc() }}</p> </div> </template> <script> export default { data () { return { a: 2, b: 3, c: 4 } }, computed: { product: function() { console.log("Product called!"); return this.a * this.b; } }, methods: { productFunc: function() { console.log("ProductFunc called!"); return this.a * this.b; } } } </script> Cada vez que el usuario cambia el valor de entrada para a o b , tanto product como productFunc se registran en la consola. Si el usuario cambia c , solo se llama a productFunc .
Volviendo a Angular, mobxjs realmente ayuda con este problema:
npm install --save mobx-angular mobxobservable y computed para propiedades enlazadasarchivo TS
import { observable, computed } from 'mobx-angular'; @Component({ selector: 'home', templateUrl: './home.component.html', animations: [slideInDownAnimation] }) export class HomeComponent extends GenericAnimationContainer { @observable a: number = 2; @observable b: number = 3; @observable c: number = 4; getAB = () => { console.log("getAB called"); return this.a * this.b; } @computed get AB() { console.log("AB called"); return this.a * this.b; } }Margen
<div *mobxAutorun> <p>A = <input type="number" [(ngModel)]="a" /> </p> <p>B = <input type="number" [(ngModel)]="b" /> </p> <p>C = <input type="number" [(ngModel)]="c" /> </p> <p> A * B = {{ getAB() }}</p> <p> A * B (get) = {{ AB }}</p> </div> Si se cambia a o b , se llama a AB una vez y se llama a getAB varias veces. Si se cambia c , solo se llama a getAB . Por lo tanto, esta solución es más eficiente incluso cuando se deben realizar cálculos .
En algunos casos, el uso de Pure Pipe puede ser una alternativa razonable, obviamente eso viene con algunas restricciones, pero al menos evita el costo de ejecutar la función en cualquier evento.
@Pipe({ name: 'join' }) export class JoinPipe implements PipeTransform { transform(separator: string, ...strings: string[]) { return strings.join(separator); } } En su plantilla, en lugar de una propiedad de nombre completo, es posible que pueda usar ' ' | join:firstname:lastname . Es bastante triste que las propiedades calculadas todavía no existan para angular.