درس Ngrx و Angular 2: بناء تطبيق تفاعلي

نشرت: 2022-03-11

نتحدث كثيرًا عن البرمجة التفاعلية في العالم الزاوي. يبدو أن البرمجة التفاعلية و Angular 2 يسيران جنبًا إلى جنب. ومع ذلك ، بالنسبة لأي شخص ليس على دراية بكلتا التقنيتين ، يمكن أن يكون مهمة شاقة لمعرفة ما يدور حوله كل شيء.

في هذه المقالة ، من خلال إنشاء تطبيق Angular 2 التفاعلي باستخدام Ngrx ، ستتعلم ماهية النمط ، وأين يمكن أن يكون النمط مفيدًا ، وكيف يمكن استخدام النمط لإنشاء تطبيقات Angular 2 أفضل.

Ngrx هي مجموعة من مكتبات Angular للامتدادات التفاعلية. تنفذ Ngrx / Store نمط Redux باستخدام مراقبات RxJS المعروفة في Angular 2. وهي توفر العديد من المزايا من خلال تبسيط حالة التطبيق الخاصة بك إلى كائنات عادية ، وفرض تدفق بيانات أحادي الاتجاه ، والمزيد. تسمح مكتبة Ngrx / Effects للتطبيق بالتواصل مع العالم الخارجي من خلال إثارة الآثار الجانبية.

ما هي البرمجة التفاعلية؟

البرمجة التفاعلية مصطلح تسمعه كثيرًا هذه الأيام ، لكن ماذا يعني ذلك حقًا؟

البرمجة التفاعلية هي طريقة تتعامل بها التطبيقات مع الأحداث وتدفق البيانات في تطبيقاتك. في البرمجة التفاعلية ، تقوم بتصميم مكوناتك وأجزاء أخرى من برنامجك من أجل التفاعل مع هذه التغييرات بدلاً من طلب التغييرات. هذا يمكن أن يكون نقلة كبيرة.

أداة رائعة للبرمجة التفاعلية ، كما تعلم ، هي RxJS.

من خلال توفير الملاحظات والكثير من المشغلين لتحويل البيانات الواردة ، ستساعدك هذه المكتبة في التعامل مع الأحداث في تطبيقك. في الواقع ، باستخدام العناصر القابلة للملاحظة ، يمكنك رؤية الحدث على أنه تيار من الأحداث وليس حدثًا لمرة واحدة. يتيح لك ذلك دمجها ، على سبيل المثال ، لإنشاء حدث جديد تستمع إليه.

البرمجة التفاعلية هي تحول في الطريقة التي تتواصل بها بين أجزاء مختلفة من التطبيق. بدلاً من دفع البيانات مباشرة إلى المكون أو الخدمة التي تحتاجها ، في البرمجة التفاعلية ، فإن المكون أو الخدمة هي التي تتفاعل مع تغييرات البيانات.

كلمة عن Ngrx

لفهم التطبيق الذي ستقوم بإنشائه من خلال هذا البرنامج التعليمي ، يجب أن تقوم بالغطس السريع في مفاهيم Redux الأساسية.

متجر

يمكن اعتبار المتجر على أنه قاعدة بيانات من جانب العميل ، ولكن الأهم من ذلك أنه يعكس حالة تطبيقك. يمكنك رؤيتها على أنها المصدر الوحيد للحقيقة.

إنه الشيء الوحيد الذي تغيره عندما تتبع نمط Redux وتقوم بتعديله بإرسال الإجراءات إليه.

المخفض

المخفضات هي الوظائف التي تعرف ما يجب فعله بإجراء معين والحالة السابقة لتطبيقك.

ستأخذ المخفضات الحالة السابقة من متجرك وتطبق وظيفة خالصة عليها. نقي يعني أن الدالة ترجع دائمًا نفس القيمة لنفس المدخلات وليس لها أي آثار جانبية. من نتيجة تلك الوظيفة البحتة ، سيكون لديك حالة جديدة سيتم وضعها في متجرك.

أجراءات

الإجراءات هي الحمولة التي تحتوي على المعلومات المطلوبة لتغيير متجرك. بشكل أساسي ، يحتوي الإجراء على نوع وحمولة ستأخذها وظيفة المخفض لتغيير الحالة.

المرسل

المرسلون هم مجرد نقطة دخول لك لإرسال عملك. في Ngrx ، توجد طريقة إرسال مباشرة في المتجر.

الوسيطة

البرامج الوسيطة هي بعض الدوال التي من شأنها اعتراض كل إجراء يتم إرساله من أجل إحداث آثار جانبية ، على الرغم من أنك لن تستخدمها في هذه المقالة. يتم تنفيذها في مكتبة Ngrx / Effect ، وهناك فرصة كبيرة لأنك ستحتاج إليها أثناء إنشاء تطبيقات في العالم الحقيقي.

لماذا تستخدم Ngrx؟

تعقيد

يقلل تدفق البيانات المخزن وأحادي الاتجاه بشكل كبير من الاقتران بين أجزاء من التطبيق الخاص بك. يقلل هذا الاقتران المنخفض من تعقيد تطبيقك ، لأن كل جزء يهتم فقط بحالات معينة.

الأدوات

يتم تخزين الحالة الكاملة لتطبيقك في مكان واحد ، لذلك من السهل الحصول على عرض شامل لحالة التطبيق الخاص بك والمساعدة أثناء التطوير. أيضًا ، مع Redux يأتي الكثير من أدوات التطوير الرائعة التي تستفيد من المتجر ويمكن أن تساعد في إعادة إنتاج حالة معينة من التطبيق أو السفر عبر الزمن ، على سبيل المثال.

البساطة المعمارية

يمكن تحقيق العديد من فوائد Ngrx مع حلول أخرى ؛ بعد كل شيء ، إعادة هو نمط معماري. ولكن عندما تضطر إلى إنشاء تطبيق مناسب تمامًا لنمط Redux ، مثل أدوات التحرير التعاونية ، يمكنك بسهولة إضافة ميزات باتباع النمط.

على الرغم من أنك لست مضطرًا للتفكير فيما تفعله ، فإن إضافة بعض الأشياء مثل التحليلات من خلال جميع تطبيقاتك يصبح أمرًا تافهًا حيث يمكنك تتبع جميع الإجراءات التي يتم إرسالها.

منحنى التعلم الصغير

نظرًا لأن هذا النمط مُعتمد على نطاق واسع وبسيط ، فمن السهل حقًا على الأشخاص الجدد في فريقك اللحاق بسرعة بما قمت به.

تتألق Ngrx أكثر عندما يكون لديك الكثير من الجهات الفاعلة الخارجية التي يمكنها تعديل تطبيقك ، مثل لوحة معلومات المراقبة. في هذه الحالات ، يكون من الصعب إدارة جميع البيانات الواردة التي يتم دفعها إلى تطبيقك ، وتصبح إدارة الحالة صعبة. هذا هو سبب رغبتك في تبسيطها بحالة غير قابلة للتغيير ، وهذا شيء يوفره لنا متجر Ngrx.

بناء تطبيق باستخدام Ngrx

تتألق قوة Ngrx أكثر عندما يكون لديك بيانات خارجية يتم دفعها إلى تطبيقنا في الوقت الفعلي. مع وضع ذلك في الاعتبار ، دعونا نبني شبكة بسيطة للمستقلين تُظهر المستقلين عبر الإنترنت وتسمح لك بالتصفية من خلالها.

إنشاء المشروع

Angular CLI هي أداة رائعة تعمل على تبسيط عملية الإعداد بشكل كبير. قد ترغب في عدم استخدامه ولكن ضع في اعتبارك أن بقية هذه المقالة ستستخدمه.

 npm install -g @angular/cli

بعد ذلك ، تريد إنشاء تطبيق جديد وتثبيت جميع مكتبات Ngrx:

 ng new toptal-freelancers npm install ngrx --save

المخفض لحسابهم الخاص

المخفضات هي جزء أساسي من بنية Redux ، فلماذا لا تبدأ بها أولاً أثناء إنشاء التطبيق؟

أولاً ، قم بإنشاء مخفض "لحسابهم الخاص" سيكون مسؤولاً عن إنشاء حالتنا الجديدة في كل مرة يتم فيها إرسال إجراء إلى المتجر.

freelancer-grid / freelancers.reducer.ts

 import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array<IFreelancer> } export interface IFreelancer { name: string, email: string, thumbnail: string } export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); default: return state; } }

إذن ها هو مخفض المترجمين المستقلين.

سيتم استدعاء هذه الوظيفة في كل مرة يتم فيها إرسال إجراء من خلال المتجر. إذا كان الإجراء هو FREELANCERS_LOADED ، فسيتم إنشاء مصفوفة جديدة من حمولة الإجراء. إذا لم يكن كذلك ، فسيعيد مرجع الحالة القديم ولن يتم إلحاق أي شيء.

من المهم أن نلاحظ هنا أنه في حالة إرجاع مرجع الحالة القديم ، سيتم اعتبار الحالة دون تغيير. هذا يعني أنه إذا اتصلت بـ state.push(something) ، فلن يتم اعتبار الحالة قد تغيرت. ضع ذلك في الاعتبار أثناء القيام بوظائف المخفض.

الدول غير قابلة للتغيير. يجب إرجاع حالة جديدة في كل مرة تتغير فيها.

مكون شبكة العامل المستقل

قم بإنشاء مكون شبكة لإظهار المستقلين عبر الإنترنت. في البداية ، سوف يعكس فقط ما هو موجود في المتجر.

 ng generate component freelancer-grid

ضع ما يلي في freelancer-grid.component.ts

 import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component.html', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.Observable<Array<IFreelancer>>; constructor(private store: Store<AppState>) { this.freelancers = store.select('freelancers'); } }

وما يلي في freelancer-grid.component.html :

 <span class="count">Number of freelancers online: {{(freelancers | async).length}}</span> <div class="freelancer fade thumbail" *ngFor="let freelancer of freelancers | async"> <button type="button" class="close" aria-label="Close" (click)="delete(freelancer)"><span aria-hidden="true">&times;</span></button><br> <img class="img-circle center-block" src="{{freelancer.thumbnail}}" /><br> <div class="info"><span><strong>Name: </strong>{{freelancer.name}}</span> <span><strong>Email: </strong>{{freelancer.email}}</span></div> <a class="btn btn-default">Hire {{freelancer.name}}</a> </div>

إذن ماذا فعلت للتو؟

أولاً ، قمت بإنشاء مكون جديد يسمى freelancer-grid .

يحتوي المكون على خاصية تسمى freelancers وهي جزء من حالة التطبيق الموجودة في متجر Ngrx. باستخدام عامل التشغيل المحدد ، تختار أن يتم إعلامك فقط من خلال خاصية العاملين freelancers بحالة التطبيق الإجمالية. لذلك الآن في كل مرة تتغير فيها خاصية العاملين freelancers لحالة التطبيق ، سيتم إعلامك الذي يمكن ملاحظته.

الشيء الوحيد الجميل في هذا الحل هو أن المكون الخاص بك يحتوي على تبعية واحدة فقط ، وهو المتجر الذي يجعل المكون أقل تعقيدًا ويمكن إعادة استخدامه بسهولة.

من جانب القالب ، لم تفعل شيئًا معقدًا للغاية. لاحظ استخدام الأنبوب غير المتزامن في *ngFor . العاملون freelancers الذين يمكن ملاحظتهم ليسوا قابلين للتكرار بشكل مباشر ، ولكن بفضل Angular ، لدينا الأدوات لفك غلافه وربط dom بقيمته باستخدام الأنبوب غير المتزامن. هذا يجعل العمل مع ما يمكن ملاحظته أسهل بكثير.

إضافة وظيفة إزالة العاملين لحسابهم الخاص

الآن بعد أن أصبح لديك قاعدة وظيفية ، دعنا نضيف بعض الإجراءات إلى التطبيق.

تريد أن تكون قادرًا على إزالة المستقل من الدولة. وفقًا لكيفية عمل Redux ، تحتاج أولاً إلى تحديد هذا الإجراء في كل حالة تتأثر به.

في هذه الحالة ، ما هو إلا المخفض freelancers :

 export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } }

من المهم حقًا هنا إنشاء مصفوفة جديدة من المجموعة القديمة للحصول على حالة جديدة غير قابلة للتغيير.

الآن ، يمكنك إضافة وظيفة حذف المستقلين إلى المكون الخاص بك والذي سيرسل هذا الإجراء إلى المتجر:

 delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) }

ألا يبدو هذا بسيطًا؟

يمكنك الآن إزالة عامل مستقل معين من الولاية ، وسيتم نشر هذا التغيير من خلال تطبيقك.

الآن ماذا لو أضفت مكونًا آخر إلى التطبيق لترى كيف يمكنهم التفاعل بين بعضهم البعض من خلال المتجر؟

مخفض المرشح

كالعادة ، لنبدأ بالمخفض. بالنسبة لهذا المكون ، فهو بسيط للغاية. تريد أن يقوم المخفض دائمًا بإرجاع حالة جديدة مع الخاصية التي أرسلناها فقط. يجب أن يبدو كالتالي:

 import { Action } from '@ngrx/store'; export interface IFilter { name: string, email: string, } export const ACTIONS = { UPDATE_FITLER: 'UPDATE_FITLER', CLEAR_FITLER: 'CLEAR_FITLER', } const initialState = { name: '', email: '' }; export function filterReducer( state: IFilter = initialState, action: Action): IFilter { switch (action.type) { case ACTIONS.UPDATE_FITLER: // Create a new state from payload return Object.assign({}, action.payload); case ACTIONS.CLEAR_FITLER: // Create a new state from initial state return Object.assign({}, initialState); default: return state; } }

مكون المرشح

 import { Component, OnInit } from '@angular/core'; import { IFilter, ACTIONS as FilterACTIONS } from './filter-reducer'; import { Store } from '@ngrx/store'; import { FormGroup, FormControl } from '@angular/forms'; import * as Rx from 'RxJS'; @Component({ selector: 'app-filter', template: '<form class="filter">'+ '<label>Name</label>'+ '<input type="text" [formControl]="name" name="name"/>'+ '<label>Email</label>'+ '<input type="text" [formControl]="email" name="email"/>'+ '<a (click)="clearFilter()" class="btn btn-default">Clear Filter</a>'+ '</form>', styleUrls: ['./filter.component.scss'], }) export class FilterComponent implements OnInit { public name = new FormControl(); public email = new FormControl(); constructor(private store: Store<any>) { store.select('filter').subscribe((filter: IFilter) => { this.name.setValue(filter.name); this.email.setValue(filter.email); }) Rx.Observable.merge(this.name.valueChanges, this.email.valueChanges).debounceTime(1000).subscribe(() => this.filter()); } ngOnInit() { } filter() { this.store.dispatch({ type: FilterACTIONS.UPDATE_FITLER, payload: { name: this.name.value, email: this.email.value, } }); } clearFilter() { this.store.dispatch({ type: FilterACTIONS.CLEAR_FITLER, }) } }

أولاً ، لقد أنشأت نموذجًا بسيطًا يتضمن نموذجًا يحتوي على حقلين (الاسم والبريد الإلكتروني) يعكس حالتنا.

يمكنك الاحتفاظ بهذه الحقول متزامنة مع الحالة بشكل مختلف تمامًا عما فعلته مع حالة freelancers . في الواقع ، كما رأيت ، لقد اشتركت في حالة التصفية ، وفي كل مرة ، يتم تشغيلك بتعيين القيمة الجديدة إلى formControl .

الشيء الوحيد الجيد في Angular 2 هو أنه يوفر لك الكثير من الأدوات للتفاعل مع العناصر التي يمكن ملاحظتها.

لقد رأيت الأنبوب غير المتزامن سابقًا ، والآن ترى فئة formControl التي تتيح لك إمكانية ملاحظة قيمة الإدخال. هذا يسمح بأشياء خيالية مثل ما فعلته في مكون المرشح.

كما ترى ، يمكنك استخدام Rx.observable.merge للجمع بين اثنين من الملاحظات التي قدمتها formControls الخاصة بك ، ثم تقوم بإلغاء تلك الملاحظة الجديدة قبل تشغيل وظيفة filter .

بكلمات أبسط ، أنت تنتظر ثانية واحدة بعد تغيير أي من الاسم أو البريد الإلكتروني formControl ثم استدعاء وظيفة filter .

أليس هذا رائعًا؟

يتم كل ذلك في بضعة أسطر من التعليمات البرمجية. هذا هو أحد الأسباب التي تجعلك تحب RxJS. يتيح لك القيام بالكثير من تلك الأشياء الفاخرة بسهولة والتي كانت ستصبح أكثر تعقيدًا لولا ذلك.

الآن دعنا ننتقل إلى وظيفة التصفية هذه. ماذا تعمل، أو ماذا تفعل؟

إنه يرسل إجراء UPDATE_FILTER بقيمة الاسم والبريد الإلكتروني ، ويتكفل المخفض بتغيير الحالة بهذه المعلومات.

دعنا ننتقل إلى شيء أكثر إثارة للاهتمام.

كيف تجعل هذا المرشح يتفاعل مع شبكة العمل المستقل التي أنشأتها مسبقًا؟

بسيط. ما عليك سوى الاستماع إلى جزء التصفية من المتجر. دعونا نرى كيف تبدو الكود.

 import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import { IFilter, ACTIONS as FilterACTIONS } from './../filter/filter-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.Observable<Array<IFreelancer>>; public filter: Rx.Observable<IFilter>; constructor(private store: Store<AppState>) { this.freelancers = Rx.Observable.combineLatest(store.select('freelancers'), store.select('filter'), this.applyFilter); } applyFilter(freelancers: Array<IFreelancer>, filter: IFilter): Array<IFreelancer> { return freelancers .filter(x => !filter.name || x.name.toLowerCase().indexOf(filter.name.toLowerCase()) !== -1) .filter(x => !filter.email || x.email.toLowerCase().indexOf(filter.email.toLowerCase()) !== -1) } ngOnInit() { } delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) } }

الأمر ليس أكثر تعقيدًا من ذلك.

مرة أخرى ، استخدمت قوة RxJS للجمع بين حالة المرشح والمستقلين.

في combineLatest ، سوف يتم applyFilter تقوم بإرجاع ملف جديد يمكن ملاحظته يقوم بذلك. لا يتعين علينا تغيير أي سطور أخرى من التعليمات البرمجية.

لاحظ كيف أن المكون لا يهتم بكيفية الحصول على المرشح أو تعديله أو تخزينه ؛ إنها تستمع إليها فقط كما تفعل مع أي دولة أخرى. لقد أضفنا للتو وظيفة التصفية ولم نضف أي تبعيات جديدة.

جعلها تلمع

تذكر أن استخدام Ngrx يضيء حقًا عندما يتعين علينا التعامل مع البيانات في الوقت الفعلي؟ دعنا نضيف هذا الجزء إلى تطبيقنا ونرى كيف ستسير الامور.

تقديم freelancers-service .

 ng generate service freelancer

ستعمل خدمة المستقلّين على محاكاة العملية في الوقت الفعلي على البيانات ويجب أن تبدو هكذا.

 import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-grid/freelancer-reducer'; import { Http, Response } from '@angular/http'; @Injectable() export class RealtimeFreelancersService { private USER_API_URL = 'https://randomuser.me/api/?results=' constructor(private store: Store<AppState>, private http: Http) { } private toFreelancer(value: any) { return { name: value.name.first + ' ' + value.name.last, email: value.email, thumbail: value.picture.large, } } private random(y) { return Math.floor(Math.random() * y); } public run() { this.http.get(`${this.USER_API_URL}51`).subscribe((response) => { this.store.dispatch({ type: ACTIONS.FREELANCERS_LOADED, payload: response.json().results.map(this.toFreelancer) }) }) setInterval(() => { this.store.select('freelancers').first().subscribe((freelancers: Array<IFreelancer>) => { let getDeletedIndex = () => { return this.random(freelancers.length - 1) } this.http.get(`${this.USER_API_URL}${this.random(10)}`).subscribe((response) => { this.store.dispatch({ type: ACTIONS.INCOMMING_DATA, payload: { ADD: response.json().results.map(this.toFreelancer), DELETE: new Array(this.random(6)).fill(0).map(() => getDeletedIndex()), } }); this.addFadeClassToNewElements(); }); }); }, 10000); } private addFadeClassToNewElements() { let elements = window.document.getElementsByClassName('freelancer'); for (let i = 0; i < elements.length; i++) { if (elements.item(i).className.indexOf('fade') === -1) { elements.item(i).classList.add('fade'); } } } }

هذه الخدمة ليست مثالية ، لكنها تفعل ما تفعله ، وللأغراض التجريبية ، تتيح لنا عرض بعض الأشياء.

أولاً ، هذه الخدمة بسيطة للغاية. يستعلم عن واجهة برمجة تطبيقات المستخدم ويدفع النتائج إلى المتجر. إنه لا يحتاج إلى تفكير ، ولا يتعين عليك التفكير في أين تذهب البيانات. يذهب إلى المتجر ، وهو ما يجعل Redux مفيدًا وخطيرًا في نفس الوقت - لكننا سنعود إلى هذا لاحقًا. بعد كل عشر ثوانٍ ، تختار الخدمة عددًا قليلاً من المستقلين وترسل عملية لحذفهم بالإضافة إلى عملية إلى عدد قليل من المستقلين الآخرين.

إذا أردنا أن يكون المخفض الخاص بنا قادرًا على التعامل معه ، فنحن بحاجة إلى تعديله:

 import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array<IFreelancer> } export interface IFreelancer { name: string, email: string, } export const ACTIONS = { LOAD_FREELANCERS: 'LOAD_FREELANCERS', INCOMMING_DATA: 'INCOMMING_DATA', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.INCOMMING_DATA: action.payload.DELETE.forEach((index) => { state.splice(state.indexOf(action.payload), 1); }) return Array.prototype.concat(action.payload.ADD, state); case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } }

الآن نحن قادرون على التعامل مع مثل هذه العمليات.

الشيء الوحيد الذي تم توضيحه في هذه الخدمة هو أنه من بين جميع عمليات تغيير الحالة التي تتم بشكل متزامن ، من المهم جدًا ملاحظة ذلك. إذا كان تطبيق الحالة غير متزامن ، فسيتم استدعاء this.addFadeClassToNewElements(); لن يعمل لأن عنصر DOM لن يتم إنشاؤه عند استدعاء هذه الوظيفة.

أنا شخصياً أجد ذلك مفيداً للغاية ، لأنه يحسن القدرة على التنبؤ.

تطبيقات البناء ، الطريقة التفاعلية

من خلال هذا البرنامج التعليمي ، قمت بإنشاء تطبيق تفاعلي باستخدام Ngrx و RxJS و Angular 2.

كما رأيت ، هذه أدوات قوية. يمكن أيضًا اعتبار ما قمت ببنائه هنا تنفيذًا لبنية Redux ، و Redux قوي في حد ذاته. ومع ذلك ، فإنه يحتوي أيضًا على بعض القيود. بينما نستخدم Ngrx ، فإن هذه القيود تنعكس حتمًا في الجزء الذي نستخدمه من تطبيقنا.

النموذج التفاعلي

الرسم البياني أعلاه هو تقريبي للهندسة المعمارية التي قمت بها للتو.

قد تلاحظ أنه حتى إذا كانت بعض المكونات تؤثر على بعضها البعض ، فإنها مستقلة عن بعضها البعض. هذه سمة مميزة لهذه البنية: تشترك المكونات في تبعية مشتركة ، وهي المتجر.

شيء خاص آخر حول هذه البنية هو أننا لا نسمي الوظائف ولكننا نطلق الإجراءات. قد يكون أحد البدائل لـ Ngrx هو إنشاء خدمة تدير حالة معينة فقط باستخدام عناصر يمكن ملاحظتها لتطبيقاتك واستدعاء وظائف على تلك الخدمة بدلاً من الإجراءات. بهذه الطريقة ، يمكنك الحصول على مركزية الدولة وتفاعلها مع عزل الحالة الإشكالية. يمكن أن يساعدك هذا الأسلوب في تقليل النفقات العامة لإنشاء مخفض ووصف الإجراءات كأشياء عادية.

عندما تشعر أن حالة تطبيقك يتم تحديثها من مصادر مختلفة وتبدأ في التسبب في الفوضى ، فإن Ngrx هو ما تحتاجه.

الموضوعات ذات الصلة: جميع الامتيازات ، بلا متاعب: دروس 9 Angular