Разбиране на Flux, реактивната архитектура на facebook
Какво е Flux?
Flux е архитектурата, която екипът на Facebook използва при работа с React. Това не е рамка или библиотека, това е нов архитектурен подход, който допълва React и принципа на еднопосочния поток от данни.
Facebook обаче предоставя хранилище, което съдържа изпълнението на Dispatcher. Диспечерът действа като глобален брокер в модела издател-абонат (Pub/sub) и разпределя полезния товар към регистрираните манипулатори.
Типична реализация на архитектурата на Flux може да използва тази библиотека, заедно с класа EventEmitter на NodeJS, за изграждане на система, управлявана от събития, за да помогне за управлението на състоянието на приложението.
Flux вероятно е най-лесно да се обясни по отношение на неговите компоненти:
- Действия / Действия - помощници, които опростяват прехвърлянето на данни към диспечера
- Диспечер / Диспечер - приема Действия и изпраща товара до регистрирани манипулатори
- Магазини / Магазини - контейнери за състоянието на приложението и бизнес логиката в манипулатори, регистрирани в Диспечера
- Контролерни изгледи / изгледи - Реагирайте компоненти, които събират състоянието на магазините и го предават на дъщерни компоненти чрез свойства
Нека да видим как изглежда този процес на диаграма:
Как API се справя с това?
По мое мнение използването на Actions за предаване на данни към Stores чрез поток на Flux е най-малко болезненият начин за справяне с данни, идващи извън вашата програма или излизащи извън нея.
Диспечер / Диспечер
Какво е диспечер?
По същество Диспечерът е мениджърът на целия този процес. Това е централният възел на вашето приложение. Диспечер получавакъм входа на действие и разпределя тези действия (и свързаните с тях данни) на регистрирани манипулатори.
Значи това всъщност е pub/sub?
Не точно. Диспечерът излъчва данни към ВСИЧКИ манипулатори, регистрирани с него, и позволява манипулаторите да бъдат извиквани в определен ред, дори да чакат актуализации, преди да продължат. Има само един диспечер и той действа като централен център за цялото ви приложение.
Ето как може да изглежда:
В примера по-горе създаваме метода Dispatcher и handleViewAction. Тази абстракция е полезна, ако ще разделяте действията, създадени в интерфейса, и действията, идващи от сървъра/API.
Следващата диаграма илюстрира този процес:
Зависимости
Едно от хубавите неща за описаната реализация на Dispatcher е способността да се описват зависимости и да се контролира редът на изпълнение на манипулаторите в хранилищата. Така че, ако един от компонентите на приложението зависи от друг, който трябва да бъде актуализиран, преди той да покаже правилно състоянието, методът waitFor на Dispatcher е полезен.
За да използвате тази функция, трябва да съхраните стойността, върната от регистърния метод на Dispatcher в свойството dispatcherIndex на Store, както е показано по-долу:
След това в магазина, докато обработваме действието, можем да използваме метода waitFor на диспечера, за да се уверим, че ShoeStore вече е обработил действието и е актуализирал данните:
Напр. пер.: Кен Уилър, очевидно, описва остарялата реализация на Dispatcher, защото в текущата версия методът waitFor има различен подпис.
Магазини
Магазините във Flux управляват състоянието на конкретни части от домейна на вашето приложение. За ощеНа високо ниво това означава, че хранилищата съхраняват данни, методи за получаване на тези данни и манипулатори на действия, регистрирани в диспечера.
Нека да разгледаме едно просто хранилище:
Най-важното нещо, което направихме в примера по-горе, е да добавим възможности на NodeJS EventEmitter към нашия магазин. Това позволява на магазините да слушат и изпращат събития, което от своя страна позволява на компонентите за преглед да се актуализират въз основа на тези събития. Тъй като нашият изглед слуша събитието „промяна“, излъчвано от магазините, той знае, че състоянието на приложението се е променило и е време да получи (и покаже) текущото състояние.
Също така регистрирахме манипулатора с нашия AppDispatcher, използвайки неговия метод за регистриране. Това означава, че нашето хранилище вече слуша за известия от AppDispatcher. Въз основа на получените данни операторът switch решава дали можем да обработим действието. Ако действието е обработено, се задейства събитие „промяна“ и изгледите, които се абонират за това събитие, отговарят, като актуализират състоянието си:
Изгледът използва метода getShoes на интерфейса Store, за да получи всички обувки от вътрешния обект _shoes и да предаде тези данни на компонентите. Това е много прост пример, но тази архитектура позволява на компонентите да останат доста спретнати дори когато се използва по-сложна логика вместо Views.
Action Creators & Действия / Фабрика за действия и действия
Фабрика за действие е набор от методи, които се извикват от Views (или където и да е другаде), за да изпращат действия към диспечера. Действията са полезният товар, който Диспечерът изпраща на абонатите.
В реализацията на Facebook Действията се разграничават по тип - константа,който се изпраща заедно с данните за действие. В зависимост от типа, действията могат да се обработват по подходящ начин в регистрирани манипулатори, като данните от тези действия се използват като аргументи за вътрешни методи.
По-горе използвахме библиотеката keyMirror на React, за да, познахте, създадем обект със стойности, идентични на неговите ключове. Само като погледнем този файл, можем да кажем, че нашето приложение може да зарежда обувки. Използването на константи поддържа нещата организирани и ви помага бързо да оцените възможностите на приложението.
В горния пример създадохме метод в нашия обект ShoeStoreActions, който предава посочените данни на нашия диспечер. Вече можем да заредим този файл от нашия API (или Views, например) и да извикаме метода ShoeStoreActions.loadShoes(ourData), за да предадем полезния товар на Dispatcher, който ще го разпространи до абонатите. По този начин ShoeStore ще знае за това събитие и ще извика метода за зареждане на обувки.
Изгледи на контролера
Изгледите са само компоненти на React, които се абонират за събитието „промяна“ и получават състоянието на приложението от магазините. След това те предават тези данни на дъщерни компоненти чрез свойства.
Ето как изглежда:Напр. per.: В текущата версия на React компонентите се създават малко по-различно.
В примера по-горе ние се абонираме за актуализации на Store с помощта на addChangeListener и актуализираме нашето състояние, когато получим събитие „промяна“.
Състоянието на приложението се съхранява в нашите магазини, така че ние използваме интерфейса на магазините, за да получим тези данни и след това да актуализираме състоянието на компонентите.
Сглобяване на всичко
Сега, след като преминахме през всички основничасти от архитектурата на Flux, разбираме по-добре как тази архитектура всъщност работи. Спомняте ли си нашата диаграма на процеса от началото на статията? Нека да ги разгледаме малко по-подробно, тъй като вече разбираме функциите на всяка част от потока:
Заключение
След като използвате Flux, ще почувствате, че писането на React приложения без Flux е като манипулиране на DOM без jQuery. Да, възможно е, но изглежда по-малко елегантно и подредено.
Ако искате да се придържате към архитектурата на Flux, но не харесвате React, опитайте Delorean, рамка на Flux, която може да се комбинира с Ractive.js или Flight. Друга библиотека, която заслужава да се отбележи, е Fluxxor, която използва малко по-различен подход към архитектурата на Flux и включва по-тясно свързване на компонентите на Flux като част от един екземпляр.
Вярвам, че за да разберете напълно Flux, трябва да го изпитате, така че очаквайте четвъртата и последна част от поредицата за обучение на React, където ще изградим прост онлайн магазин, използвайки React.js и архитектурата на Flux.
И тук можете да получите грант за тестов период на Yandex.Cloud. Необходимо е само да въведете "Habr" в полето "секретна парола".