Недавно я попытался использовать библиотеки управления состоянием Redux и MobX для React, однако, если вы реализуете более сложные страницы с большим количеством привязок (например, 1000), повторный рендеринг всей VDOM для одного изменение собственности государства. Поэтому я попытался реализовать библиотеку, которая бы повторно отображала только те компоненты, которые прослушивают используемую привязку.
В ViewModel вы можете определять наблюдаемые объекты, массивы и действия. Чтобы изменить значение любого значения, вы можете использовать функцию this.set (похожую на действие redux), которая установит значение наблюдаемого, но компоненты, которые прослушивают эту привязку, будут повторно визуализированы позже при вызове this.applyChanges.
export class ArrayViewModel extends ViewModel {
todo: Observable<string> = new Observable("");
todos: ObservableArray<string>
= new ObservableArray(
[
new Observable("milk"),
new Observable("carrot")
]
);
addTodo = () => {
this.set(this.todos, [ ...this.todos.get(), new Observable(this.todo.get())]);
this.set(this.todo, "");
this.applyChanges();
}
}
Вам нужно будет расширить тип Component и прикрепить хранилище (аналогично redux) с вашей ViewModel (состоянием). Чтобы напечатать любое значение, вы можете использовать функцию this.bind, которая будет регистрировать компонент для обновлений свойства.
export class ArrayComponent extends Component<ArrayViewModel, ArrayComponentProps, {}> {
constructor(props: ArrayComponentProps) {
super(props);
}
componentDidMount() {
}
render() {
return (
<div>
<p>
<Textbox store={this.store} text={this.vm.todo} />
<button onClick={this.vm.addTodo}>
Add Todo
</button>
</p>
<ul>
{this.bind(this.vm.todos).map(todo => {
return (
<li key={todo.id}>
<Literal store={this.store} text={todo} />
</li>
);
})}
</ul>
<ul>
{this.bind(this.vm.todos).map(todo => {
return (
<li key={todo.id}>
<Textbox store={this.store} text={todo} />
</li>
);
})}
</ul>
</div>
);
}
}
В компоненте действие set в хранилище можно легко вызвать при изменении (повторно отображает только текущий компонент) и применить к размытию (повторно отобразит все компоненты, использующие ту же привязку);
export class Textbox<TProps extends TextboxProps, TState>
extends Component<ViewModel, TProps, TState> {
constructor(props: TProps & ComponentProps) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange(e: React.ChangeEvent<HTMLInputElement>) {
this.change(this.props.text, e.target.value);
if (this.props.onChange) {
this.props.onChange(e);
}
}
render() {
return (
<input
type="text"
value={this.bind(this.props.text)}
onChange={this.handleChange}
onBlur={this.applyChanges}
/>
);
}
}
Это не будет быстрее с добавлением, удалением или сортировкой массива, но будет намного быстрее визуализировать изменения любых значений элементов массива.
Я понимаю, что все можно было бы сделать проще, используя декораторы (у меня еще нет этого навыка), но я хотел бы спросить, считаете ли вы, что такой подход может повлиять на производительность сложных компонентов, написанных на React. Я новичок в React, и, возможно, мне что-то не хватает, поэтому, пожалуйста, дайте мне знать ваше мнение.