programing

앵귤러는 vue.js와 같은 "슬립 속성" 기능을 가지고 있습니까?

stoneblock 2023. 8. 7. 22:18

앵귤러는 vue.js와 같은 "슬립 속성" 기능을 가지고 있습니까?

저는 Vue.js를 먼저 배웠고, 지금은 Angular 4에 프로젝트가 있어서 Angular만 배웠습니다.저는 "컴퓨팅된 속성"을 제외한 모든 것이 Vue와 크게 다르지 않다는 것을 알게 되었습니다.Vue에서는 다른 속성의 변경 내용을 수신하는 계산된 속성을 생성하고 계산을 자동으로 실행할 수 있습니다.

예를 들어(Vue 2)

computed: {
    name(){
        return this.firstname + ' ' + this.lastname;
    }
}

이름 속성은 이름 또는 성이 변경된 경우에만 다시 계산됩니다.Angular 2 또는 4에서 이를 처리하는 방법은 무엇입니까?

이것은 이미 답변이 되었지만 저는 이것이 매우 좋은 답변이 아니라고 생각하며 사용자들은 게터를 각도로 계산된 속성으로 사용해서는 안 됩니다.왜 물으시겠어요?getter는 함수에 대한 sugar 구문일 뿐이며 일반 함수로 컴파일됩니다. 이것은 모든 변경 감지 검사에서 실행된다는 것을 의미합니다.이는 성능에 좋지 않습니다. 자산이 변경될 때마다 수백 번 재계산되기 때문입니다.

다음 예를 살펴 보십시오. 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;
    }
}

계산된 속성을 가지고 싶다면 mobx와 같은 상태 컨테이너를 사용할 수 있습니다.

class TodoList {
    @observable todos = [];
    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}

mobx에는 @descriptor가 있으므로 getter 속성은 필요할 때만 캐시되고 다시 계산됩니다.

으로 더 발전할 수 있도록 노력하겠습니다.Andzej Maciusovic공인답얻길바있습다니 다음할 수 .실제로 VueJS에는 다음과 같은 예를 사용하여 신속하게 표시할 수 있는 계산된 속성이라는 기능이 있습니다.

<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>

a또는b,둘다요.product그리고.productFunc콘솔에 로깅하는 중입니다.사용자가 변경된 경우c, 친구들.productFunc이 호출됩니다.

Angular로 돌아가서, mobxjs는 이 문제에 정말 도움이 됩니다.

  1. 다을사여설을 사용하여 합니다.npm install --save mobx-angular mobx
  2. 사용하다observable그리고.computed 속성

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;
       }
    }

마크업

<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>

한다면a또는b변경되었습니다.AB는 한 번, 그리고 번호며되출한라고 불립니다.getAB여러 번. 만약에.c 변었습다니경만 변경되었습니다.getAB이 호출됩니다.따라서솔루션은 계산을 수행해야 하는 경우에도 더욱 효율적입니다.

computedVue의 속성에는 반응성과 메모화라는 두 가지 큰 이점이 있습니다.

Vue에서는 다른 속성의 변경 내용을 수신하는 계산된 속성을 생성하고 계산을 자동으로 실행할 수 있습니다.

당신은 여기서 구체적으로 Angular의 반응성 시스템에 대해 묻고 있습니다.사람들은 Angular 초석이 무엇인지 잊은 것 같습니다: 관찰 가능한 것.

const { 
    BehaviorSubject, 
    operators: {
      withLatestFrom,
      map
    }
} = rxjs;
const firstName$ = new BehaviorSubject('Larry');
const lastName$ = new BehaviorSubject('Wachowski');

const fullName$ = firstName$.pipe(
    withLatestFrom(lastName$),
    map(([firstName, lastName]) => `Fullname: ${firstName} ${lastName}`)
);

const subscription = fullName$.subscribe((fullName) => console.log(fullName))

setTimeout(() => {
    firstName$.next('Lana');
    subscription.unsubscribe();
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.js"></script>

내 코드는 메모 부분을 해결하지 않고 반응성만 해결합니다.

사람들은 몇 가지 흥미로운 대답을 했습니다.하는 동안에mobX computed속성은 (mobX를 사용해 본 적이 없음) 무엇에 더 가까운 것일 수 있습니다.computedVueis에서는 사용할 흥미가 없을 수도 있는 다른 라이브러리에 의존하고 있음을 의미합니다.파이프 대안은 반응성과 메모화를 모두 다루기 때문에 설명한 특정 사용 사례에 대해 여기서 가장 흥미롭지만 모든 경우에 유효한 것은 아닙니다.

경우에 따라 Pure Pipe를 사용하는 것이 합리적인 대안이 될 수 있습니다. 분명히 몇 가지 제한 사항이 수반되지만 적어도 모든 이벤트에서 기능을 실행하는 데 드는 비용을 방지할 수 있습니다.

@Pipe({ name: 'join' })
export class JoinPipe implements PipeTransform {
  transform(separator: string, ...strings: string[]) {
    return strings.join(separator);
  }
}

전체이속대템플서사있수다니습용할에릿을 할 수 있습니다.' ' | join:firstname:lastname계산된 속성이 여전히 각도에 대해 존재하지 않는다는 것은 꽤 슬픈 일입니다.

네, 가능합니다.

TS 파일:

export class MyComponent {

  get name() {
     return  this.firstname + ' ' + this.lastname;
  }
}

그리고 HTML에서 그 뒤에:

<div>{{name}}</div>

다음은 예입니다.

@Component({
  selector: 'my-app',
  template: `{{name}}`,
})
export class App  {
  i = 0;
  firstN;
  secondN;

  constructor() {
    setInterval(()=> {
      this.firstN = this.i++;
      this.secondN = this.i++;
    }, 2000);
  }
  get name() {
    return  this.firstN + ' ' + this.secondN;
  }
}

Vue composition API에서 두 가지 기능을 가져올 수 있으며 매우 잘 작동합니다.이것은 나쁜 생각일 수도 있지만, 재미있습니다.만만 가져오기ref그리고.computedVue에서 각의 계산된 속성을 가질 수 있습니다.

Angular 프로젝트에 Vue를 추가한 PR의 예가 있습니다. https://github.com/kevin-castify/vue-in-angular/pull/1/files

  1. 버전 3 이상을 사용하여 프로젝트에 Vue 추가
  2. 다음과 같이 구성 요소에 추가합니다.
import { Component, OnInit } from '@angular/core';
import { ref, watch } from 'vue';

...

export class FullNameComponent implements OnInit {
  firstName = ref('');
  lastName = ref('');
  fullName = computed(() => this.firstName.value + this.lastName.value;

  ngOnInit(): void {
    // Might need to seed the refs here to trigger the first computation
    firstName.value = "Jane";
    lastName.value = "Doe";
  }
}

언급된 방법이 모든 요구를 100% 충족시키지 못하기 때문에 옵션(TypeScript 4)을 하나 더 추가하고자 합니다.그것은 반응적이지 않지만 여전히 충분히 좋습니다.이 아이디어는 변화를 감지하는 함수와 속성 값을 계산하는 함수를 명시적으로 선언하는 것입니다.

export class ComputedProperty<TInputs extends any[], TResult> {
    private readonly _changes: (previous: TInputs) => TInputs;
    private readonly _result: (current: TInputs) => TResult;
    private _cache: TResult;
    private _inputs: TInputs;

    constructor(changes: (previous: TInputs) => TInputs, result: (current: TInputs) => TResult) {
        this._changes = changes;
        this._result = result;
    }

    public get value(): TResult {
        const inputs = this._changes(this._inputs);
        if (inputs !== this._inputs) {
            this._inputs = inputs;
            this._cache = this._result(this._inputs);
        }
        return this._cache;
    }
}

선언:

// readonly property
this.computed = new ComputedProperty<[number], number>(
        (previous) => {
            return previous?.[0] === this.otherNumber ? previous : [this.otherNumber];
        },
        (current) => {
            return current[0] + 1;
        }
    );

사용:

 <label>Angular computed property: {{computed.value}}</label>

업데이트(2023년 5월)

Angular 16 https://angular.io/api/core/computed 의 Angular 릴리스 계산 값 기능

기본적으로 각도에서는 Vuejs와 유사한 계산된 속성이 필요하지 않습니다.새 프레임워크로 이동한 후에는 이전의 기능과 솔루션을 잊어버리고 새로운 프레임워크의 기능과 솔루션을 적용하고 활용해야 합니다.각도에서 템플릿의 데이터 조작 방법은 여러 가지가 있지만 규칙이 있습니다.

템플릿에서 게터와 같은 메서드 호출 방지

대신 몇 가지 다른 방법이 있습니다.

파이프
관찰 가능한 항목
표현.
ng모델

데이터 흐름과 요구 사항에 따라 하나를 선택합니다.

언급URL : https://stackoverflow.com/questions/43710642/does-angular-have-the-computed-property-feature-like-in-vue-js