react学习笔记之context、Fragment、PrueComponent

context之于react-redux

context在props、state、refs三大属性外另一属性。可以使用context属性在祖组件中进行数据共享。
在react中有个createContext()可以创建context对象,返回的组件中有两个组件Provider、Consumer。

Provider组件要包裹子组件,并且只有一个value属性,值为要共享的数据。
Consumer组件是支持函数组件和类组件使用的,Provider仅能在类组件中使用。

import React from 'react';

const MyContext = React.createContext();
//MyContext.Provider还可以这样获取 
const {Provider} = MyContext;
export default class App extends React.Component{
	state = {thing:'apple'};
    render(){
    	const {thing} = this.state;
        return (
        	<div>
				<div>这是父组件 App</div>
				<div>父组件中有个{thing}</div>
				//Provider要包裹子组件,让父组件的后代组件可以使用context对象
				/**联想到react-redux中的Provider组件了
					在入口文件中将App组件包裹起来让App下的其他组件都可以使用store
				*/
				//<MyContext.Provider value={thing}>
				<Provider value={thing}>
					<B/>
				</Provider>
				//<MyContext.Provider>
			</div>
        );
}
class B extends React.Component{
    render(){
    	return (
    		<div>
    		    <div>这是子组件 B</div>
    		    <C/>
    		</div>
    	);
}
class C extends React.Component{
	//在孙组件中使用context就要声明
	static contextType = MyContext;
	render(){
		return (
			<div>
				<div>这是孙组件 C</div>
				<div>孙组件中知道父组件有个{this.context}</div>
			</div>
		);
}
//如果想共享多个数据,value还可以是一个对象,那就是以下写法:
//<Provider value={{data:{a:'a'},thing:'apple'}}
//孙组件内获取的context就是this.context.thing

//要是孙组件是函数没法使用this怎么办呢?不怕,咱们还有Consumer组件
/**
function C(){
	return (
		<div>
			<div>这是孙组件</div>
			<div>孙组件中知道父组件有个
			<MyContext.Consumer>
				{ value =>value.thing }
			</MyContex.Consumer>
		</div>
	};
}
*/

Fragment ——层级嵌套终结者

看以上代码,App组件是多层结构所以要有个父div盒子包裹,B组件、C组件也要用div包裹,那就造成了很多不必要的<div>
要想不使用div包裹每个组件,可以使用react中的Fragment组件包裹。它不会出现在HTML结构中。
当然,还有一个方法就是用<></>包裹。

import React,{Fragment} from 'react';

export default class App extends Component{
	render(){
		return (
			<Fragment>
				<div>这里有些东西</div>
				<div>&nbsp;&nbsp:</div>
			</Fragment>
		);
}

PrueComponent与Component

较于Component,PrueComponent为类组件提供了更严格的重新渲染规则,提高了效率。

Component存在问题:

  1. 父组件重新渲染后不管子组件有没有使用父组件的状态,子组件也会被渲染。
  2. 调用this.setState({})没有改变状态也会重新渲染组件。

PrueComponent原理使用shouldComponentUpdata()生命周期,将前状态和后状态进行比较,相同返回false不重新渲染。

PrueComponent存在问题:
        当你通过浅拷贝获取state对象后,进行状态的修改再传递给setState时,因为PrueComponent会对比引用地址,所以会造成无法重新渲染的情况。

import React,{Compoennt,Fragment} from 'react';

export default class App extends Component{
	state = {apple:'apple'};
	change = ()=>{
		this.setState({});
	}
	//shouldComponentUpdata有两个参数,可以获取之后修改后的props和state
	shouldComponentUpdata(nextProps,nextState){
	//如果apple没改变,就不进行重新渲染
		if(this.state.apple === nextState.apple){
			return false;
		}else{
			return true;
		}
	}
	render(){
		console.log('render---A');
		return (
			<Fragment>
				<div>这是A组件</div>
				<B/>
				<button onClick={this.change}>点击测试</button>
			</Fragment>
		);
}
class B extends React.Component{
	//在子组件中也可以使用shouldComponentUpdata判断props是否改变
	//shouldComponentUpdata(nextPorps){...}
    render(){
    	console.log('render--B');
    	return (
    		<>
    		    <div>这是子组件 B</div>
    		    <C/>
    		</>
    	);
}
	//只有一个state属性还好,但是如果有二十个state属性呢?
	//就可以使用react提供的PrueComponent
	//只用将App、B组件继承Component修改为继承PrueComponent就行
	/**
	PrueComponent存在问题:
	state={apple:'apple',data:['test']};
	change=()=>{
		const {data} = this.state;
		data.unshift('banana');
		this.setState({...this.state,data});
		//这时即使data数组确实改变了,但是引用地址是相同的,会被判定为未修改状态而不重新渲染
		//所以修改状态最好就是传入新数据
		this.setState({...this.state,data:[...this.state.data,'banana']});
		//上面写的可能有点绕,可以看以下的例子理解一下
		const obj = {a:'apple',b:'banana',c:'pear',b:'pineapple'};
		console.log(obj.b);//pineapple
	*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值