برنامه نویسی

سیگنال زاویه ای: مدیریت حالت واکنشی

Angular دائما در حال تکامل است و یکی از جدیدترین نوآوری هایی که به اکوسیستم معرفی شده است سیگنال. این ویژگی که از مفاهیم واکنش پذیری الهام گرفته شده است، نوید تغییر روشی را می دهد که توسعه دهندگان Angular با حالت های واکنشی و ارتباط بین کامپوننت ها برخورد می کنند.

ما آنچه را که سیگنال، چگونه کار می کند و چگونه می توان از آن برای عملکرد بیشتر برنامه های Angular و نگهداری آسان تر استفاده کرد.

چیست سیگنال انگولار نیست؟

آنها یک API واکنشی جدید هستند که در Angular معرفی شده اند که مدیریت داده و واکنش پذیری در برنامه ها را بر اساس الگویی به نام ساده می کند. الگوی طراحی ناظر. با توجه به این الگو داریم یک ناشر که مقداری مقدار را به همراه فهرستی از مشترکین کسانی که به آن علاقه مند هستند، و هنگامی که مقدار تغییر می کند، یک اعلان دریافت می کنند.

توضیحات تصویر
در اصل، سیگنال:

  • یک مقدار واکنشی را ذخیره می کند.
  • هنگامی که مقدار تغییر می کند به طور خودکار به مصرف کنندگان اطلاع می دهد.
  • نوشتن کد واکنشی را آسان تر می کند.

چرا استفاده کنید سیگنال ها انگولار نیست؟

  • Simplicity: آنها ایجاد حالت های واکنشی را ساده می کنند. در مقایسه با قابل مشاهده انجام دهید RxJS، به کد کمتری برای پیکربندی نیاز دارند و برای مبتدیان Angular بصری تر هستند.

  • عملکرد: به‌روزرسانی‌ها و نماهای حالت را بهینه کنید. فقط اجزایی که مستقیماً به a وابسته هستند سیگنال به روز می شوند و از رندرهای غیر ضروری اجتناب می شود.

  • وابستگی های کمتر: به آن وابسته نباشید RxJS برای سناریوهای اساسی این منحنی یادگیری را کاهش می دهد و انتقال به Angular را آسان تر می کند.

  • مقیاس پذیری: برای کارکرد کامل در معماری های پیچیده طراحی شده اند.

چگونه در Angular کار می کنند؟

Os سیگنال ها در Angular سه مفهوم اصلی وجود دارد:

  • ایجاد سیگنال ها: شما یک را ایجاد می کنید سیگنال برای ذخیره یک مقدار واکنشی

  • خواندن سیگنال ها: می توانید به مقدار دسترسی داشته باشید سیگنال مستقیما

  • به روز رسانی از سیگنال ها: می توانید مقدار را تغییر دهید و به مصرف کنندگان اطلاع دهید.

دستمان را کثیف کنیم!

برای تغییر مقدار سیگنال.

  • اولی توسط مجموعه که تعریف می کند سیگنال به یک مقدار جدید؛

app.component.html


Nosso Signal: {{exemploSignal()}}



وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app.component.ts

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterOutlet,
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
})
export class AppComponent {
  title = 'exemplos';

  protected exemploSignal = signal('angular');

  constructor() {
  }

  executar(){
    this.exemploSignal.set('Framework Angular');
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  • دومی توسط به روز رسانی کنید که بر اساس مقدار فعلی تنظیم می شود.

app.component.html


Nosso Signal: {{exemploCount()}}



وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app.component.ts

import { Component, signal } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterOutlet,
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
})
export class AppComponent {
  title = 'exemplos';

  protected exemploCount = signal(1);

  constructor() {
  }

  executar(){
    this.exemploCount.update(atual => atual + 1);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

1 – مثال شمارنده

برای مثال اول، یک شمارنده بسیار ساده برای آزمایش دانش ایجاد خواهیم کرد.

contador.component.html

class="container"> Contador: {{ contador() }}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

contador.component.css

:host {
  display: block;
}

.container {
  display: flex;
  gap: 10px;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

contador.component.ts

import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-contador',
  standalone: true,
  imports: [],
  templateUrl: './contador.component.html',
  styleUrl: './contador.component.css'
})
export class ContadorComponent {
contador = signal(0);

  incrementar(){
    this.contador.update(valor => valor + 1);
  }

  decrementar(){
    this.contador.update(valor => valor - 1);
  }

  limpar(){
    this.contador.set(0);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چه بازی در این کد، در حال حاضر وجود دارد سیگنال که یک مقدار اولیه به خط اضافه می کنیم:

contador = signal(0);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در توابع افزایش و کاهش از تابع استفاده می کنیم به روز رسانی کنید انجام دهید سیگنال قابل نوشتن برای گرفتن مقدار قبلی و افزایش یا کاهش یک مقدار جدید.

  incrementar(){
    this.contador.update(valor => valor + 1);
  }

  decrementar(){
    this.contador.update(valor => valor - 1);
  }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

برای تمیز کردن استفاده شد، تابع مجموعه برای اضافه کردن یک مقدار جدید اما بدون در نظر گرفتن مقدار قبلی.

حال چگونه می توانیم از به روز رسانی ارزش در html استفاده کنیم؟ بسیار ساده است که مقدار تغییر یافته را در نما نشان دهید و فقط آن را به عنوان “عملکرد” ​​صدا کنید.

  Contador: {{ contador() }} 
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

2 – سیگنال های محاسبه شده

سیگنال ها محاسبه شده اند سیگنال ها فقط خواندنی که ارزش خود را از دیگران می گیرند سیگنال ها. تو تعریف کن سیگنال ها با استفاده از تابع محاسبه می شود محاسبه شده است و مشخص کردن یک مشتق:

  contador = signal(0);
  contadorVezesDois: Signal<number> = computed(() => this.contador() * 2);
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال ما، زمانی که مقدار کنتادور به روز می شود accountantTimesTwo تغییر خواهد کرد زیرا بستگی به آن دارد کنتادور.

o کد کامل:

contador-v2.component.html

class="container"> Contador: {{ contador() }}

class="result"> Valor do contador vezes 2: {{ contadorVezesDois() }}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

contador-v2.component.css

:host {
  display: block;
}

.container {
  display: flex;
  gap: 10px;
}

.result{
  margin-top: 10px;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

counter-v2.component.ts

import { Component, computed, Signal, signal } from '@angular/core';

@Component({
  selector: 'app-contador-v2',
  standalone: true,
  imports: [],
  templateUrl: './contador-v2.component.html',
  styleUrl: './contador-v2.component.css'
})
export class ContadorV2Component {
  contador = signal(0);
  contadorVezesDois: Signal<number> = computed(() => this.contador() * 2);

  incrementar(){
    this.contador.update(valor => valor + 1);
  }

  decrementar(){
    this.contador.update(valor => valor - 1);
  }

  limpar(){
    this.contador.set(0);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

3 – جلوه ها

سیگنال مصرف کنندگان علاقه مند را هنگام تغییر مطلع کنید. اثر عملیاتی است که هر زمان یک یا چند مقدار از آن انجام می شود سیگنال تغییر دهید.

برای این مثال، اجازه دهید یک سرویس ایجاد کنیم ریشه.

import { Injectable, signal } from "@angular/core";

@Injectable({ providedIn: 'root' })
export class Store {
  contador = signal(0);

  incrementar(){
    this.contador.update(valor => valor + 1);
  }

  decrementar(){
    this.contador.update(valor => valor - 1);
  }

  limpar(){
    this.contador.set(0);
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

مولفه شمارنده اکنون به این شکل خواهد بود.

contador-v3.component.html

class="container"> Contador: {{ store.contador() }}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

contador-v3.component.css

:host {
  display: block;
}

.container {
  display: flex;
  gap: 10px;
}

.result{
  margin-top: 10px;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

counter-v3.component.ts

import { Component, inject } from '@angular/core';
import { Store } from '../store';

@Component({
  selector: 'app-contador-v3',
  standalone: true,
  imports: [],
  templateUrl: './contador-v3.component.html',
  styleUrl: './contador-v3.component.css'
})
export class ContadorV3Component {
 protected store = inject(Store);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در حال حاضر app.component، ما داریم اثر.


وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

import { Component, effect, inject } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ContadorV3Component } from './contador-v3/contador-v3.component';
import { Store } from './store';
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterOutlet,
    ContadorV3Component,
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
})
export class AppComponent {
  protected store = inject(Store)

  constructor() {
    effect(() => {
      const contador = this.store.contador();
      if(contador < 0) {
        console.log('Negativo')
      }
      else{
      const par = contador % 2 === 0;
      if(par) {
        console.log('Par')
      } else {
        console.log('Impar')
      }
    }
    });
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بنابراین زمانی که افزایش، کاهش یا پاک شدن به اطلاع می رسد اثر، جایی که من یک پرینت کنسول ساده انجام دادم.

  • اثر حداقل یک بار فعال خواهد شد.
  • اثر حداقل پس از یکی از آن ها فعال می شود سیگنال که به تغییر آن بستگی دارد (مقدار آن را می خواند).
  • اثر حداقل تعداد دفعات فراخوانی خواهد شد. این بدان معناست که اگر چندین سیگنال ها که از آن اثر بستگی به تغییر مقادیر آنها در همان زمان دارد، کد فقط یک بار اجرا می شود.

4 – روی Push Compooent

Angular فقط زمانی تغییرات را بررسی می‌کند ورودی تغییر می کند یا رویدادی راه اندازی می شود. بنابراین اگر جزء شما استفاده می کند changeDetection: ChangeDetectionStrategy.OnPush، تغییرات فقط در DOM موارد ذکر شده توسط ما

در مثال اول، یک ویژگی به نام ایجاد می کنیم شجاعت و یک تایمر در سازنده قرار دهید که افزایش می یابد. حتی با افزایش در شجاعت روی نمایشگر روشن تأثیر نمی گذارد DOM.

on-push-teste.component.ts

import { ChangeDetectionStrategy, Component, signal } from "@angular/core";

@Component({
  selector: 'app-on-push-teste',
  standalone: true,
  template: `
    
    

O valor é: {{valor}}

`
, changeDetection: ChangeDetectionStrategy.OnPush }) export class OnPushTesteComponent { valor = 1; constructor(){ setInterval(() => { this.valor++; console.log('Mudou o valor: ', this.valor); }, 1000); } }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کنسول در حال افزایش است:

توضیحات تصویر

صفحه نمایش تغییر نمی کند:

توضیحات تصویر

با این حال، زمانی که ما استفاده می کنیم سیگنال رفتار کاملا متفاوت است، به شرح زیر است:

on-push-teste.component.ts

import { ChangeDetectionStrategy, Component, signal } from "@angular/core";

@Component({
  selector: 'app-on-push-teste',
  standalone: true,
  template: `
    
    

O valor é: {{valor()}}

`
, changeDetection: ChangeDetectionStrategy.OnPush }) export class OnPushTesteComponent { valor = signal(1); constructor(){ setInterval(() => { this.valor.update(valor => valor + 1); console.log('Mudou o valor: ', this.valor()); }, 1000); } }
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون صفحه مقدار افزایش یافته است:

توضیحات تصویر

app.component.html


وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

app.component.ts

import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { OnPushTesteComponent } from './on-push-teste/on-push-teste.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    RouterOutlet,
    OnPushTesteComponent
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
})
export class AppComponent {

  constructor() {
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

چرا این اتفاق می افتد؟ اکنون چگونه آن را تعریف کنیم

ts valor = signal(1);

به عنوان سیگنال، هر تغییری در آن نشان می دهد که مقدار جدید باید ارائه شود.

کد کامل: Github

مرجع:

سیگنال های زاویه ای

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا