ComponentKit и архитектура FLUX - избегайте ненужного повторного рендеринга пользовательского интерфейса
Я использую Facebook ComponentsKit для генерации своих просмотров.
Сейчас я перехожу на "потоковую" архитектуру для изменения состояния приложения и запуска обновлений представления.
Основная проблема у меня заключается в том, что не все изменения состояния должны вызывать обновление пользовательского интерфейса. Я не понимаю "общего" механизма, чтобы этого избежать.
По сути, состояние приложения - это "большой" "JSON", представляющий "модель представления" (анализируется на объектах с типизированным типом). JSON содержит все объявления представления и их начальные значения. (JSON довольно сложный)
Например, упрощенный JSON, представляющий иерархию представления, содержащую компонент "пейджер" и кнопку "Далее" навигации:
{
... views ...
{
"pager" : {
"id" : "pager-id-xxx",
"currentPage" : 0,
"pages" : [
....pages....
{},
{},
....pages....
]
},
...
"navigation-next-button" : {
"id" : "navigation-next-button-id-xxxx",
"target" : "pager-id-xxx"
}
},
... views ...
}
Моя абстракция "Flux" выглядит так:
// "Action" portion
@interface ChangePageAction
@property id destinationId; // very simplified action. wraps the destination "id"
@end
@implementation ChangePageReducer
-(JSON)reduce:(JSON)initialJSON action:(ChangePageAction *)changePageAction {
// the "reduce" portion finds the node of the pager (in the JSON) and changes the value by +1
// something like:
// find the node in the JSON with the changePageAction.destinationID
Node *nodeCopy = getNodeCopy(initialJSON,changePageAction.destinationId);
replaceValue(nodeCopy,nodeCopy.currentPage + 1);
// according to FLUX doctrine we are supposed to return a new object
return jsonCopyByReplacingNode(nodeCopy); // a new JSON with the updated values
}
// the navigation button triggers the new state
@implementation NavigationNextButton {
id _destination; // the target of this action
FluxStore _store; // the application flux store
}
-(void)buttonPressed {
ChangePageAction *changePage = ...
[_store dispatch:changePage];
}
@end
В моем "контроллере вида" я теперь получаю обратный вызов "состояние обновления"
@implementation ViewController
-(void)newState:(JSON)newJSON {
// here all of the view is re-rendered
[self render:JSON];
//The issue is that I don't need or want to re-render for every action that is performed on the state.
// many states don't evaluate to a UI update
// how should I manage that?
}
@end
1 ответ
К сожалению, в ComponentKit нет простого способа сделать это. Реагировать имеет shouldComponentUpdate
, но у ComponentKit нет эквивалента.
Хорошей новостью является то, что ComponentKit должен быть достаточно умным, чтобы перестраивать все компоненты, а затем понимать, что на самом деле ничего не изменилось, и в конечном итоге не вносить никаких изменений в UIKit.
Плохая новость в том, что на это уйдет немало ресурсов процессора.