Недавно я попытался использовать библиотеки управления состоянием 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();
}
}
Вам потребуется расширить тип компонента и присоединить хранилище (аналогично приставке) с помощью вашей 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 для store может быть легко вызвано при изменении (повторно отображает только текущий компонент) и применено к размытию (повторно отобразятся все компоненты, использующие одну и ту же привязку);
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 и могу что-то упустить, поэтому, пожалуйста, дайте мне знать ваше мнение.