返回介绍

不可变数据和纯粹渲染

发布于 2025-02-17 12:51:32 字数 2687 浏览 0 评论 0 收藏 0

我们之前已经讨论了许多关于不可变数据的红利,但是,当它和 react 结合时还会有一个非常屌的好处:
如果我们创建纯 react 组件并传递给它不可变数据作为属性参数,我们将会让 react 在组件渲染检测中得到最大性能。

这是靠 react 提供的 PureRenderMixin 实现的。
当该 mixin 添加到组件中后,组件的更新检查逻辑将会被改变,由深比对改为高性能的浅比对。

我们之所以可以使用浅比对,就是因为我们使用的是不可变数据。如果一个组件的所有参数都是不可变数据,
那么将大大提高应用性能。

我们可以在单元测试里更清楚的看见差别,如果我们向纯组件中传入可变数组,当数组内部元素产生改变后,组件并不会
重新渲染:

//test/components/Voting_spec.jsx

it('renders as a pure component', () => {
  const pair = ['Trainspotting', '28 Days Later'];
  const component = renderIntoDocument(
    <Voting pair={pair} />
  );

  let firstButton = scryRenderedDOMComponentsWithTag(component, 'button')[0];
  expect(firstButton.getDOMNode().textContent).to.equal('Trainspotting');

  pair[0] = 'Sunshine';
  component.setProps({pair: pair});
  firstButton = scryRenderedDOMComponentsWithTag(component, 'button')[0];
  expect(firstButton.getDOMNode().textContent).to.equal('Trainspotting');
});

如果我们使用不可变数据,则完全没有问题:

//test/components/Voting_spec.jsx

import React from 'react/addons';
import {List} from 'immutable';
import Voting from '../../src/components/Voting';
import {expect} from 'chai';

const {renderIntoDocument, scryRenderedDOMComponentsWithTag, Simulate}
  = React.addons.TestUtils;

describe('Voting', () => {

  // ...

  it('does update DOM when prop changes', () => {
    const pair = List.of('Trainspotting', '28 Days Later');
    const component = renderIntoDocument(
      <Voting pair={pair} />
    );

    let firstButton = scryRenderedDOMComponentsWithTag(component, 'button')[0];
    expect(firstButton.getDOMNode().textContent).to.equal('Trainspotting');

    const newPair = pair.set(0, 'Sunshine');
    component.setProps({pair: newPair});
    firstButton = scryRenderedDOMComponentsWithTag(component, 'button')[0];
    expect(firstButton.getDOMNode().textContent).to.equal('Sunshine');
  });
});

如果你跑上面的两个测试,你将会看到非预期的结果:因为实际上 UI 在两种场景下都更新了。那是因为现在组件
依然使用的是深比对,这正是我们使用不可变数据想极力避免的。

下面我们在组件中引入 mixin,你就会拿到期望的结果了:

//src/components/Voting.jsx

import React from 'react/addons';
import Winner from './Winner';
import Vote from './Vote';

export default React.createClass({
  mixins: [React.addons.PureRenderMixin],
  // ...
});

//src/components/Vote.jsx

import React from 'react/addons';

export default React.createClass({
  mixins: [React.addons.PureRenderMixin],
  // ...
});

//src/components/Winner.jsx

import React from 'react/addons';

export default React.createClass({
  mixins: [React.addons.PureRenderMixin],
  // ...
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文