针对复杂组件的更快的React状态管理

时间:2018-11-18 20:20:14

标签: reactjs mvvm react-redux mobx mobx-react

最近,我尝试将Redux和MobX状态管理库用于React,但是,如果您要实现具有大量绑定(例如1000)的更复杂的页面,则重新呈现整个VDOM会有点慢对于状态的单个属性更改。因此,我试图实现仅重新呈现那些侦听所用绑定的组件的库。

在ViewModel中,您可以定义Observable对象,数组和动作。要更改任何值,可以使用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类型,并使用ViewModel(状态)附加存储(类似于redux)。要打印任何值,可以使用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}
        />
    );
}
}

添加,删除或排序数组不会更快,但是呈现任何数组项值的更改会更快。

enter image description here

我知道使用装饰器可以使所有事情变得更容易(尚不具备此技能),但是我想问一下您是否认为这种方法会对React中编写的复杂组件产生性能影响。我对React很陌生,可能会遗漏一些东西,所以请告诉我您的意见。

2 个答案:

答案 0 :(得分:0)

不要重新发明轮子。

更复杂的用例需要对内部反应工作方式有更深入的了解。 最重要的两件事避免render 并使渲染结果“稳定” /纯(对于相同的道具具有相同的结果)-避免实际的DOM更新(作为对帐的结果)(与VDOM /实际DOM不同)。

您应该从头开始-正常反应状态和标准优化(docs):shouldComponentUpdatePureComponent等。

您可以直接在this.props.onChange中使用render(使用propTypes使其为必需)。 绑定render会影响性能-每个render调用都会创建一个新的引用并强制进行实际的DOM更新。

答案 1 :(得分:0)

我认为@xadm 已经涵盖了大部分内容。对相同内容再添加一些内容。

当涉及到重新审视复杂问题时,结构、状态和性能概念非常重要。 React 提供的概念可帮助您提高应用程序性能。

它采用 lifting state up 方法在组件之间共享状态。在这里,您觉得需要一个更好的结构来管理组件间状态。尽管采用这种方法并不是一个坏主意,但在您这样做之前,您需要了解 React 的性能概念。 React.PureComponent 在上述情况下。

很长一段时间以来,我一直在使用 Rootz JS 处理非常复杂的情况。因为它可以很好地处理复杂的状态变化。它也帮助我构建我的应用程序。

有一个使用 Rootz JS 制作的示例 Todo App。如果您想看一眼。

这是 source code 的样子。

<块引用>

我喜欢您可能感兴趣的 Concept of Contracts