React性能优化之Context

栏目: IOS · Android · 发布时间: 5年前

内容简介:react之类的mvvm框架有个痛点想必大家都遇到过,那就是祖孙组件之间的通信现在组件之间的通信规范是:仅仅是父子两个组件之间这没有问题

react之类的mvvm框架有个痛点想必大家都遇到过,那就是祖孙组件之间的通信

现在组件之间的通信规范是:

  • 父 -> 子:属性绑定props
  • 子 -> 父:事件广播(vue之类的emit)react那还是调用父类的props[fn]

仅仅是父子两个组件之间这没有问题

可是祖孙组件之间呢?

react中有个虫洞的概念,相当于直通车,组件【祖先】=> 组件【孙子】,而不需要中间的组件来代理props

下面就先介绍下高端的虫洞(直通车)

直接show code

三个组件App.js,Son.js,GrandSon.js,下面介绍的是用虫洞从App props直通GrandSon,而不需要Son来做代理属性

// App.js的代码

import React from 'react';
import Son from './son';
import PropTypes from 'prop-types';

class App extends React.Component{
    constructor(){
		super();
		
        this.state = {
            grandSonDesc: 'i am grandSonDesc'
        };
    }

    getChildContext(){
        return {
            grandSonDesc: this.state.grandSonDesc
        }
    }
    
    render(){
        return <Son />
    }
}

App.childContextTypes = {
    grandSonDesc: PropTypes.string
}

export default App;
复制代码
// Son.js

import React from 'react';
import GrandSon from './grandSon';

const Son = () => {
    return <GrandSon />
}

export default Son;
复制代码
// GrandSon.js

import React from 'react';
import PropTypes from 'prop-types';

class GrandSon extends React.Component{
    render(){
        return <div>{this.context.grandSonDesc}</div>
    }
}

GrandSon.contextTypes = {
    grandSonDesc: PropTypes.string
};

export default GrandSon;
复制代码

至此就实现了虫洞了,可是需要注意两点:

  • GrrandSon不能为纯函数组件,这样是不能注入的
  • App组件和GrandSon组件需要定义类属性contextTypes,App组件需要定义getChildContext

那么问题来了,为啥要声明contextTypes? 原因是,GrandSon组件除了App这个爷爷组件外,还有Son这个爸爸组件。那么grandSonDesc是从哪个组件继承而来呢,contextTypes就是做这个标识作用,而且多个父组件的context会做merge,也是根据定义contextTypes来的

好的,到这里感觉很爽,虫洞直通车传输props,但是我要说的是,这个实现在react17将被废弃!!!

为何老版本虫洞将被废弃?

如果一个属性将被废弃,多半是跟它的性能有关了,可以试想下,虫洞传输props,其实son组件没有任何更新,那么当grandSonDesc变化时,Son组件会不会被更新?直接show code吧

// App.js

import React from 'react';
import Son from './son';
import PropTypes from 'prop-types';

class App extends React.Component{
    constructor(){
		super();
		
        this.state = {
            grandSonDesc: 'i am grandSonDesc'
        };
	}
	
	componentDidMount(){
		setTimeout(() => {
			this.setState({
				grandSonDesc: 'i am grandSonDesc啊啊啊啊啊啊啊啊'
			});
		}, 3000);
	}

    getChildContext(){
        return {
            grandSonDesc: this.state.grandSonDesc
        }
    }
    
    render(){
        return <Son />
    }
}

App.childContextTypes = {
    grandSonDesc: PropTypes.string
}

export default App;
复制代码
// Son.js

import React from 'react';
import GrandSon from './grandSon';

class Son extends React.Component{
    componentDidUpdate(){
        console.log('son updated!');
    }

    render(){
        return <GrandSon />
    }
}

export default Son;
复制代码
// GrandSon.js

import React from 'react';
import PropTypes from 'prop-types';

class GrandSon extends React.Component{
    componentDidUpdate(){
        console.log('grandson updated!');
    }

    render(){
        return <div>{this.context.grandSonDesc}</div>
    }
}

GrandSon.contextTypes = {
    grandSonDesc: PropTypes.string
};

export default GrandSon;
复制代码

在版本的代码中,App.js在三秒钟之后去更新grandSonDesc,然后在Son和GrandSon组件中加上componentDidUpdate更新之后的log,来看一下控制台输出

React性能优化之Context

三秒之后GrandSon的显示变成了i am grandSonDesc啊啊啊啊啊啊啊啊,而控制台输出son updated

这说明Son组件也被更新了,那么虫洞如果中间层组件比较多的话,岂不是很浪费性能吗?

二代虫洞

那么既然性能不好,世界顶级前端团队就要开始优化了,那么就有了二代虫洞,直接上代码介绍下二代虫洞吧,还是原来的配方App+Son+GrandSon,唯一多的是一个context的配置文件

// App.js

import React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';

class App extends React.Component {
    constructor(){
        super();

        this.state = {
            grandSonDesc: 'i am grandSon'
        };
    }

	render(){
		return (
			<div className="App">
				<Context.Provider value={this.state}>
					<Son />
				</Context.Provider>
			</div>
		);
	}
}

App.contextType = Context;

export default App;
复制代码
// Son.js

import React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';

class Son extends PureComponent{
    render(){
        return <GrandSon />
    }
}

export default Son;
复制代码
// GrandSon.js

import React, { PureComponent } from 'react';
import Context from './context';

class GrandSon extends PureComponent{
    render(){
        return <div>
            <Context.Consumer>
                {value => value.grandSonDesc}
            </Context.Consumer>
        </div>
    }
}

export default GrandSon
复制代码
// context.js

import { createContext } from 'react';

let Context = createContext();

export default Context;
复制代码

代码敲完了,可以start看看效果了,可以发现照样跑起来了

React性能优化之Context

那么问题来了,你说一代虫洞性能差,凭什么嘛?

// App.js

import React from 'react';
import Son from './son';
import Context from './context';
import PropTypes from 'prop-types';

class App extends React.Component {
    constructor(){
        super();

        this.state = {
            grandSonDesc: 'i am grandSon'
        };
    }

    componentDidMount(){
        setTimeout(() => {
            this.setState({
                grandSonDesc: 'i am grandSon啊啊啊啊啊啊啊啊啊啊'
            });
        }, 3000);
    }

	render(){
		return (
			<div className="App">
				<Context.Provider value={{grandSonDesc: this.state.grandSonDesc}}>
					<Son />
				</Context.Provider>
			</div>
		);
	}
}

App.contextType = Context;

export default App;

复制代码
// Son.js

import React, { PureComponent } from 'react';
import GrandSon from './grandSon';
import PropTypes from 'prop-types';

class Son extends PureComponent{
    componentDidUpdate(){
        console.log('son updated');
    }

    render(){
        return <GrandSon />
    }
}

export default Son;
复制代码
// GrandSon.js

import React, { PureComponent } from 'react';
import Context from './context';

class GrandSon extends PureComponent{
    componentDidUpdate(){
        console.log('grandson updated');
    }

    render(){
        return <div>
            <Context.Consumer>
                {value => value.grandSonDesc}
            </Context.Consumer>
        </div>
    }
}

export default GrandSon
复制代码
React性能优化之Context

可以发现,3秒之后grandSonDesc变了,两个子组件的componentDidUpdated都没进

这就是两种虫洞的实现方式,到这里差不多讲完了,关于更多新版context的用法可以参考官网 reactjs.org/docs/contex…


以上所述就是小编给大家介绍的《React性能优化之Context》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Dream Machine

The Dream Machine

M. Mitchell Waldrop / Penguin Books / 2002-8 / USD 16.00

While most people may not be familiar with the name J. C. R. Licklider, he was the guiding spirit behind the greatest revolution of the modern era. At a time when most computers were big, ponderous ma......一起来看看 《The Dream Machine》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具