ارتباط بین کامپوننت ها در بلیزور

بهترین راه ارتباطی بین کامپوننت ها در بلیزور چیست؟سه تکنیک برای انجام این کار وجود دارد:EventCallbacksCascading ValuesState ContainerEventCallbacks:‫‫این ویژگی در NET Core 3 Preview 3. به بلیزور اضافه شد. که باعث می‌شود که بتوان یک کالبک برای کامپوننت ها با استفاده از Action یا Func تعریف کرد. هنگامی که ازEventCallback برای ارتباط بین کامپوننت ها استفاده شود، متد کالبک، StateHasChanged را برای رندر کردن هرگونه تغییری صدا می‌زند‌. استفاده از EventCallback برای هندل ارتباط کامپوننت های تودر تو بسیار خوب است.برای مثال تکه کد زیر را ببینید:<!-- Child Component --> <button @=”@(() => .InvokeAsync(”Hello from ChildComponent”))”>Click me</button> @code { [Parameter] public EventCallback<string> { get; set; } } <!-- Parent Component --> <ChildComponent =”ClickHandler”></ChildComponent> <p>@message</p> @code { string message = ”Hello from ParentComponent” void ClickHandler(string newMessage) { message = newMessage; } }در مثال بالا، کامپوننت فرزند دارای یک پارامتر EventCallback<string> است. کامپوننت پدر متدClickHandler خود را در ایونت فرزند ثبت کرده است. هنگامی که دکمه کلیک می شود، متد ClickHandler کامپوننت پدر با مقدار رشته invoke شده توسط فرزند فراخوانی می شود. سپس مقدار message کامپوننت پدر به طور خودکار به روز می شود.Cascading Values:مقادیر و پارامترهای Cascadeراهی برای ارسال یک مقدار از یک کامپوننت به همه فرزندان آن بدون نیاز به استفاده از پارامترهای سنتی کامپوننت است.بلیزور دارای یک کامپوننت ویژه به نام CascadingValue است. این کامپوننت اجازه می‌دهد تا هر مقداری که به آن داده می‌شود، به همه فرزندانش برساند. سپس کامپوننت های فرزند می‌تواند به ویژگی‌های نوع Cascadeشده با [CascadingParameter] دسترسی داشته باشد.این باعث می‌شود هنگام ساخت کنترل‌های UI که نیاز به مدیریت برخی حالت‌ها دارند، گزینه‌ای عالی باشند. یکی از نمونه های برجسته فرم Blazorو کامپوننت‌های اعتبار سنجی است. کامپوننت EditForm یک مقدار EditContextرا به همه کنترل‌های موجود در فرم cascadeمی‌کند. این ویژگی برای هماهنگی اعتبارسنجی و فراخوانی رویدادهای فرم استفاده می شود.<!-- Tab Container --> <h1>@SelectedTab</h1> <CascadingValue Value=”this”> @ChildContent </CascadingValue> @code { [Parameter] public RenderFragment ChildContent { get; set; } public string SelectedTab { get; private set; } public void SetSelectedTab(string selectedTab) { SelectedTab = selectedTab; StateHasChanged(); } } <!-- Tab Component --> <div @=”SetSelectedTab”>@Title @(TabContainer.SelectedTab == Title ? ”Selected&quot : ””)</div> @code { [CascadingParameter] TabContainer TabContainer { get; set; } [Parameter] public string Title { get; set; } void SetSelectedTab() { TabContainer.SetSelectedTab(Title); } }در کد بالا، ما یک کامپوننت TabContainer داریم که تبی که در حال حاضر انتخاب شده را نمایش می دهد، همچنین یک مقدار Cascade را تنظیم می کند. در این مثال، مقداری که Cascade می‌شود، خود کامپوننتTabContainer است.در کامپوننت Tab، مقدار Cascade را دریافت می کنیم و از آن برای فراخوانی متد SetSelectedTab درTabContainer هر زمان که روی div کلیک می شود استفاده می‌کنیم. همچنین مقدارSelectedTab فعلی را دوباره با استفاده از مقدار cascade شده بررسی می‌کنیم و اگر با عنوان برگه مطابقت داشت، "Selected" را به عنوان برگه اضافه می کنیم.برای بدست آوردن اطلاعات بیشتر در مورد Cascade value میتوانید این لینک را ببینید.State Container:درجات مختلفی از پیچیدگی وجود دارد که می توانید هنگام اجرای یک State Containerبه آن ها بروید. بسته به اینکه به ترتیب از Blazorسمت کلاینت یا سمت سرور استفاده می‌کنید، این می‌تواند یک کلاس ساده باشد که به‌عنوان سرویس Singleton تزریق می‌شود. یا می توانید الگوی بسیار پیچیده تری مانند Flux را پیاده سازی کنید.این راه از ۲ راه حل دیگر پیچیده تر است. با این راه حل می توان بسیاری از کامپوننت‌ها را در کل برنامه مدیریت و هماهنگ کرد.در این مثال، به استفاده از یک کلاس AppState ساده به عنوان State Container خود نگاه خواهیم کرد.public class AppState { public string SelectedColour { get; private set; } public event Action ; public void SetColour(string colour) { SelectedColour = colour; NotifyStateChanged(); } private void NotifyStateChanged() => ?.Invoke(); }این کلاس AppStateما است. رنگ فعلی انتخاب شده را ذخیره می کند و همچنین روشی را برای به روز رسانی رنگ انتخاب شده دارد. در این کلاس یک رویداد OnChangeوجود دارد، که برای هر کامپوننتی که بخواهد رنگ انتخاب شده را نشان دهد به آن نیاز است.<!-- Red Component --> @inject AppState AppState <button @=”SelectColour”>Select Red</button> @code { void SelectColour() { AppState.SetColour(”Red”); } }<!-- Blue Component --> @inject AppState AppState <button @=”SelectColour”>Select Blue</button> @code { void SelectColour() { AppState.SetColour(”Blue”); } }ما دو کامپوننت قرمز و آبی داریم. این کامپوننت‌ها فقط با کلیک روی دکمه، رنگ انتخاب شده را در AppState به روز می کنند.@inject AppState AppState @implements IDisposable @AppState.SelectedColour <RedComponent /> <BlueComponent /> @code { protected override void OnInitialized() { AppState. += StateHasChanged; } public void Dispose() { AppState. -= StateHasChanged; } }این کامپوننت آخر همه چیز را به هم پیوند می دهد. این کامپوننت رویداد OnChangeرا مدیریت می کند. هر زمان که رنگ انتخاب شده تغییر کند StateHasChangedفراخوانی می شود و کامپوننت با رنگ انتخابی جدید دوباره رندر می شود.مهم است که به یاد داشته باشید با پیاده سازی IDispsable اشتراک StateHasChanged از رویدادی را لغو کنید تا دچار Memory leak نشوید.لینک مقاله اصلی را در این آدرس می‌توانید مطالعه کنید