react与mox-react的shouldComponentUpdate 理解

react

react性能优化中,提到的就是通过 React.PureComponent 替换 React.Component 组件进行编程。

两个组件之间的不同主要就是PureComponent做了shouldComponentUpdate的优化。对props和state进行了第一层的值===比较, 并且对 context 的变化不进行判断。

通过查看React可以看到

 1 /**

2 * Copyright (c) 2013-present, Facebook, Inc.

3 * All rights reserved.

4 *

5 * This source code is licensed under the BSD-style license found in the

6 * LICENSE file in the root directory of this source tree. An additional grant

7 * of patent rights can be found in the PATENTS file in the same directory.

8 *

9 * @typechecks

10 *

11 */

12

13 /*eslint-disable no-self-compare */

14

15 'use strict';

16

17 var hasOwnProperty = Object.prototype.hasOwnProperty;

18

19 /**

20 * inlined Object.is polyfill to avoid requiring consumers ship their own

21 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is

22 */

23 function is(x, y) {

24 // SameValue algorithm

25 if (x === y) {

26 // Steps 1-5, 7-10

27 // Steps 6.b-6.e: +0 != -0

28 // Added the nonzero y check to make Flow happy, but it is redundant

29 return x !== 0 || y !== 0 || 1 / x === 1 / y;

30 } else {

31 // Step 6.a: NaN == NaN

32 return x !== x && y !== y;

33 }

34 }

35

36 /**

37 * Performs equality by iterating through keys on an object and returning false

38 * when any key has values which are not strictly equal between the arguments.

39 * Returns true when the values of all keys are strictly equal.

40 */

41 function shallowEqual(objA, objB) {

42 if (is(objA, objB)) {

43 return true;

44 }

45

46 if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {

47 return false;

48 }

49

50 var keysA = Object.keys(objA);

51 var keysB = Object.keys(objB);

52

53 if (keysA.length !== keysB.length) {

54 return false;

55 }

56

57 // Test for A's keys different from B.

58 for (var i = 0; i < keysA.length; i++) {

59 if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {

60 return false;

61 }

62 }

63

64 return true;

65 }

66

67 module.exports = shallowEqual;

shallowEqual

项目准备升级 React16,控制台出现了错误 shouldComponentUpdate should not be used when extending React.PureComponent.

一开始看很莫名其妙,明明组件没有自己写shouldComponentUpdate,怎么就报错了。

后来谷歌了下,原来是项目使用了mobx进行的状态管理。使用mox-react,对所有组件都通过 @observer 装饰器,以前也看过mobx-react源码,里面的确mixin了shouldComponentUpdate方法,优化了组件的性能

看下面的源代码

 1 function mixinLifecycleEvents(target) {

2 patch(target, "componentWillMount", true)

3 ;["componentDidMount", "componentWillUnmount", "componentDidUpdate"].forEach(function (

4 funcName

5 ) {

6 patch(target, funcName)

7 })

8 if (!target.shouldComponentUpdate) {

9 target.shouldComponentUpdate = reactiveMixin.shouldComponentUpdate

10 }

11 }

12 {

13 shouldComponentUpdate: function(nextProps, nextState) {

14 if (isUsingStaticRendering) {

15 console.warn(

16 "[mobx-react] It seems that a re-rendering of a React component is triggered while in static (server-side) mode. Please make sure components are rendered only once server-side."

17 )

18 }

19 // update on any state changes (as is the default)

20 if (this.state !== nextState) {

21 return true

22 }

23 // update if props are shallowly not equal, inspired by PureRenderMixin

24 // we could return just 'false' here, and avoid the `skipRender` checks etc

25 // however, it is nicer if lifecycle events are triggered like usually,

26 // so we return true here if props are shallowly modified.

27 return isObjectShallowModified(this.props, nextProps)

28 }

29 }

30 function isObjectShallowModified(prev, next) {

31 if (null == prev || null == next || typeof prev !== "object" || typeof next !== "object") {

32 return prev !== next

33 }

34 const keys = Object.keys(prev)

35 if (keys.length !== Object.keys(next).length) {

36 return true

37 }

38 let key

39 for (let i = keys.length - 1; i >= 0, (key = keys[i]); i--) {

40 if (next[key] !== prev[key]) {

41 return true

42 }

43 }

44 return false

45 }

经过测试,使用setState后,shouldComponentUpdate 的确 this.state!==nextState,但是对于this.props, nextProps的判断,还是存在一些差别的。

可以试下下面的比较 

console.log(isObjectShallowModified(NaN, NaN), !shallowEqual(NaN, NaN));

var a = {a: 1}, b = {b: 1, __proto__: {a: 1}};
console.log(isObjectShallowModified(a, b), !shallowEqual(a, b));

对于一些比较简单的对象比较结果还是相同的,所以对于@observer的组件就改为了React.Component进行处理。

以上是 react与mox-react的shouldComponentUpdate 理解 的全部内容, 来源链接: utcz.com/z/381120.html

回到顶部