برنامه نویسی

دو طرفه مقدار شیء ورودی سیگنال را با [(ngModel)]

به تازگی ، من با این چالش روبرو شدم … Refactor یک مؤلفه فرم برای سیگنال های زاویه ای.

مؤلفه فرم قدیمی مانند این کار می کند:

  • داده های فرم از یک سرویس دولتی واکنشی تهیه می شود
  • داده های فرم یک است اعتراض
  • قبل از انتقال به مؤلفه فرم ، داده های فرم کلون می شوند
  • مؤلفه فرم داده های فرم را از طریق یک دکوراتور کلاسیک مبتنی بر دریافت می کند زاویه ای input
@Input({required: true})
user!: User;
حالت تمام صفحه را وارد کنید

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

  • فرم استفاده می کند [(ngModel)] برای جهش شیء داده فرم
  • با کلیک بر روی دکمه ذخیره ، شیء جهش یافته را از طریق یک AngularTput به مؤلفه والدین ارسال می کند
  • مؤلفه والدین سرویس دولتی واکنشی را به روز می کند

این تنظیم در بسیاری از برنامه های ما بسیار عالی است.

شما می توانید این مجموعه را در این StackBlitz بررسی کنید که اصل اصلی را به نمایش می گذارد: فرم با AngularInput کلاسیک

Refactor به ورودی سیگنال

با ورودی سیگنال زاویه ای می توانیم ورودی های مؤلفه خود را واکنشی کنیم. این عالی به نظر می رسد!

ورودی های سیگنال FYI روش پیشنهادی برای پروژه های جدید است. از اسناد زاویه ای:

شرح تصویر

بیایید AngularNput کلاسیک خود را به ورودی سیگنال بازگردانیم:

user = input.required<User>();
حالت تمام صفحه را وارد کنید

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

مقدار شیء ورودی سیگنال و [(ngModel)]

ورودی سیگنال یک شی از نوع کاربر را دریافت می کند. ما سعی می کنیم با خصوصیات شیء متصل شویم [(ngModel)]بشر

این کد بسیار زیبا به نظر می رسد 😍!

و در این stackblitz همه چیز به نظر می رسد: با ورودی سیگنال – حالت سیگنال جهش یافته

‼ ️ منطقه خطر:

اما صبر کنید … ، ما به تازگی وارد منطقه خطر شده ایم … ☢ ☣ ⚠

در واقع چه اتفاقی می افتد؟

  • user() سیگنال ورودی را باز کنید. ما شیء کاربر خام را نگه می داریم
  • این خط کد [(ngModel)]="user().firstName" اراده جهش دادن هر زمان که مقدار ورودی متن تغییر کند ، شیء کاربر (که به یک سیگنال پیچیده شده است)

☢ جهش شیء سیگنال ☣

چرا جهش حالت سیگنال ایده بدی است؟ زیرا ما در حال دور زدن سیگنال های عمومی API برای به روزرسانی حالت هستیم. به طور معمول فقط باید از روشهای اختصاصی استفاده کنیم set یا update به منظور به روزرسانی حالت سیگنال.

سایر توسعه دهندگان ممکن است بخواهند سیگنال های دیگری را در بالای آن بسازند user سیگنال با زاویه ای computedبشر اما محاسبه هرگز تحریک نمی شود زیرا user سیگنال در مورد جهش شیء کاربر نمی داند. این ممکن است یک رفتار شگفت آور باشد.

ورودی های سیگنال فقط خواندنی هستند

و بله ، دلیل دیگری وجود دارد ، چرا استفاده [(ngModel)] در ورودی سیگنال حداقل عجیب است. قرار است ورودی های سیگنال فقط خواندنی باشند. آنها ندارند set یا update روش – بنابراین هیچ پشتیبانی رسمی برای تغییر وضعیت ورودی سیگنال به صورت برنامه ای وجود ندارد.

نجات دادن

بیایید سعی کنیم هرچه سریعتر فرار کنیم. راه حل های ممکن چیست؟

سیگنال پیوندی

با سیگنال مرتبط می توانیم یک نوشتار ایجاد کنیم کاربر سیگنال ، که به طور خودکار به روز می شود ، هر زمان که ورودی سیگنال کاربر مقدار جدیدی دریافت کند. در همان زمان می توانیم سیگنال مرتبط را با آن به روز کنیم set وت updateبشر

editableUser سیگنال مرتبط ما است …

export class UserDetailComponent {
  user = input.required<User>();
  editableUser = linkedSignal(() => this.user()); 

  updateEditableUser(v: Partial<User>) {
    this.editableUser.update(state => ({...state, ...v}))
  } 
}
حالت تمام صفحه را وارد کنید

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

ما همچنین معرفی کردیم updateEditableUser روشی که از API سیگنال عمومی برای به روزرسانی حالت سیگنال استفاده می کند: در این حالت ما تماس می گیریم update روش سیگنال مرتبط.

[(ngModel)] تقسیم شده است [ngModel] وت (ngModelChange)

  • [ngModel]="editableUser().firstName" هنگامی که اولین ویژگی نام شیء کاربر به روز شده است ، ورودی متن را به روز می کند
  • هر وقت مقدار ورودی متن تغییر می کند ، پاسخ به تماس ngmodelchange (updateEditableUser) اجرا می شود و سیگنال مرتبط به روز می شود

جوانب

  • ما از API سیگنال عمومی برای به روزرسانی حالت استفاده می کنیم
  • ما از سیگنال پیوندی استفاده می کنیم که یک سیگنال قابل نوشتن است
  • تغییرات دولت به صراحت در یک روش اختصاصی اتفاق می افتد
  • کلون شیء لازم نیست

منفی

  • برخی از دیگهای بخار لازم وجود دارد: تنظیم سیگنال مرتبط ، NGMODEL ، NGMODELCHANGE ، روش برای به روزرسانی حالت
  • در حال حاضر ، سیگنال مرتبط هنوز در پیش نمایش توسعه دهنده (Angular 19) است

StackBlitz: با ورودی سیگنال – سیگنال مرتبط

اثر

یک روش جایگزین استفاده از زاویه ای است effect برای گوش دادن به مقادیر جدید ورودی سیگنال.
وقتی مقدار جدیدی را از ورودی دریافت می کنیم ، مقدار خام را به یک ویژگی کلاس محلی اختصاص می دهیم.

export class UserDetailComponent {
  _user = input.required<User>({alias: 'user'});
  user!: User;

  constructor() {
    effect(() => this.user = this._user())
  }
}
حالت تمام صفحه را وارد کنید

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

در الگوی ما می توانیم همانطور که همیشه انجام می دادیم ، شیء خام را جهش دهیم.

جوانب

  • این الگو با مؤلفه اصلی فرم مدرسه قدیمی ما که از یک AngularInput کلاسیک استفاده می کند یکسان است
  • ما به طور رسمی یک شیء خام را جهش می دهیم (API های سیگنال را دور نمی زنیم ، حالت ورودی سیگنال فقط خواندنی را جهش نمی دهیم).

منفی

  • user: User باید اولیه شود: user: User = new User(); یا باید به TypeScript بگوییم که کاربر همیشه با آن تعریف شده است user!: User;
  • کلونینگ مورد نیاز است (در والدین با لوله ساختاری کلون اتفاق می افتد)
  • نامگذاری چالش: _user سیگنال 'user' نام مستعار ، user ویژگی برای شیء کاربر خام

stackblitz: با ورودی سیگنال – اثر

رویکرد let

با LET ، می توانیم متغیرهایی را در الگوی اعلام کنیم.

بیایید از let برای دریافت شیء خام از ورودی سیگنال کاربر استفاده کنیم. علاوه بر این ، ما همچنین می توانیم کلون را با لوله ساختاری کلون خود انجام دهیم.

Typescript:

export class UserDetailComponent {
  user = input.required<User>();
}
حالت تمام صفحه را وارد کنید

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

جوانب

  • حداقل دیگ بخار و کوچکترین کد در مقایسه مؤلفه فرم مدرسه قدیمی (input)
  • let یک مکان واحد برای اجازه دادن به جادو است (سیگنال ، کلون را باز کنید)

منفی

  • ارزش شیء لازم است ، با مقادیر ابتدایی کار نمی کند. دیدن یادداشت ها برای جزئیات بیشتر در زیر

stackblitz: با ورودی سیگنال -t

یادداشت ها

مقادیر بدوی

در مثالهای بالا ، ورودی مؤلفه یک مقدار شی (شی کاربر) دریافت کرد.
رویکردهای سیگنال و اثر مرتبط با ورودی های سیگنال که از مقادیر ابتدایی استفاده می کنند (رشته ، بولی ، تعداد …) کار می کند.

بیایید نگاهی به رویکرد let بیاندازیم:
متغیرهای Let فقط خواندنی هستند … به این معنی که نمی توانیم مقادیر جدید را به یک متغیر let تغییر دهیم. همچنین ، نه از طریق [(ngModel)]بشر اگر سعی کنیم ، می توانیم این خطای کامپایل را ببینیم:

شرح تصویر

رویکرد Let به یک مقدار شی نیاز دارد که می توانیم جهش دهیم.

پایان

به نظر می رسد “رویکرد let” مستقیم ترین راه حل با حداقل دیگ بخار است.

اثر و سیگنال مرتبط نیز گزینه های معتبری هستند ، اما نیاز به راه اندازی بیشتری دارند.

ما هنوز ارزیابی می کنیم که کدام رویکرد برای برنامه های ما مناسب ترین است و این Blogpost باید به ما در تصمیم گیری خوب کمک کند.

امیدوارم که شما از بازدید کوتاه ما از منطقه خطر جهش حالت سیگنال لذت ببرید. نظر شما در مورد استراتژی های فرار من چیست؟ من مطمئن هستم که گزینه های حتی بیشتر وجود دارد. در نظرات به من اطلاع دهید.

ممنون

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

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

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

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