zoukankan      html  css  js  c++  java
  • React 通过context(上下文)实现多组件嵌套传值的实现

    在React当中,父组件通过props给子组件传递属性的,但是当组件的嵌套层次非常多的时候,使用props传参就不是很方便了,此时可以用context来实现。类似于Vue里的provide/inject这一对选项组,实现的效果是一样的。

    React里的context只能由class组件来提供,然后class组件内的子组件就可以获取了,React里的conetxt有两种使用方法:

    • childContextType  ;经典的用法,相比较第二种方法性能不是很好
    • createContext    ;React16提供的一个新的API,通过组件来实现的,效率比较高,推荐使用这个

    方法一 childContextType使用方法

    在父组件中,我们要提供一个getChildContext方法,用于指定子节点能获取到的所有数据对象,还要在class对象上设置一个childContextTypes属性,用于指定数据的类型,例如:

    class Parent extends React.Component{
        getChildContext(){                                        //定义一个getChildContext成员函数,返回Parent组件提供的数据
            return {height:180}                                
        }
        render(){
            return <div>子节点jsx</div>
        }
    }
    
    Parent.childContextTypes = {                     //设置childContextTypes属性,用于指定getChildlContext里返回的每个键的类型
        height:PropTypes.number
    }

     writer by:大沙漠 QQ:22969969

    在组件中,我们在class对象里设置一个contextTypes属性即可,用于指定需要从父节点获取的context,可以通过this.context获取到所有能获取到的context对象,例如:

    class Child extends React.Component{
        render(){
            return <div>{this.context.height}</div>
        }
    }
    Child.contextTypes={                                 //设置contextTypes属性,这里是子组件希望从父层组件提供的context中某几个属性
        height:PropTypes.number
    }

    使用这种方法时,需要加载一个prop-types.js文件,和声明时的类型有关,script标签可以直接用这个:https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.0/prop-types.min.js,。

    举个例子:

    <div id="root"></div>    
    <script type="text/babel">
        class Parent extends React.Component{
            state = {height:180}
            getChildContext(){                                //这里提供给子组件中可以获取的对象
                return {height:this.state.height}
            }                
            render(){
                return (
                    <div>
                        <button  onClick={e=>this.setState({height:this.state.height+1})}>测试</button>
                        <Child></Child>
                    </div>
                )
            }
        }
        Parent.childContextTypes = {        
            height:PropTypes.number
        }
        
        class Child extends React.Component{
            render(){
                return <p>{this.context.height}</p>
            }
        }
        Child.contextTypes = {                
            height:PropTypes.number
        }
    
        ReactDOM.render(<Parent></Parent>,root)
    </script>

    我们在Parent组件上定义了一个button按钮,点击时会使当前的state.height+1,然后又引用了Child子组件,通过childContextType进行了值的传递,渲染如下:

    方法二 createContext方法

     这种方法是通过React16新增的一个API叫做React.createContext()来实现的,我们调用React.createContext时可以传入一个参数,参数就是默认值,返回一个对象,含有一个Provider组件和一个Consumer组件,在需要使用context(上下文)的地方直接使用即可。

    React.createContext()返回一个包含Provider和Consumer组件引用的对象,我们在需要提供数据的class组件内使用Provider组件(例如上面的Parent组件),在需要获取数据的子组件内(例如上面的Child组件),直接使用context组件即可,Provider和Consumer组件的用法如下:

    1. Provider组件     ;给该组件传递一个value属性,用于指定当前提供的数据,数据可以是任意值,数字、字符串、对象都可以
    2. Consumer组件   ;我们在显示数据的地方直接使用即可,该组件的子节点是一个函数模板,React内部会直接执行该函数,参数就是传递的值。

     我们把例1里的例子重新用createContext来写一下,如下:

    <div id="root"></div>    
    <script type="text/babel">
        const { Provider, Consumer } = React.createContext()           //调用React.createContext返回一个Provider和Consumer组件
        class Parent extends React.Component{
            state = {height:180}
            render(){                        
                return (
                    <div>
                        <button  onClick={e=>this.setState({height:this.state.height+1})}>测试</button>
                        <Provider value={{height:this.state.height}}>         //Provider组件内通过value设置contexxt
                            <Child></Child>
                        </Provider>
                        
                    </div>
                )
            }
        }
    
        class Child extends React.Component{
            render(){
                return     <p>
                                    <Consumer>{val=>val.height}</Consumer>          /子组件内通过Consumer来直接获取值,子节点是一个函数,参数是传递过来的值
                                </p>
            }
        }
    
        ReactDOM.render(<Parent></Parent>,root)
    </script>

    实现的效果和例1是一样的,就不截图演示了。

    用childContextType实现时,如果getChildContext内返回的一个值改变了,所有的子节点都将重新渲染,而用createContext实现时,如果改变了某个数据,只有引用数据的那个DOM节点对象才会重新渲染,其它DOM并不会更新,因此性能更好一点。

    官方说childContextType在React17中将被淘汰,如果淘汰了那么function组件和class组件的参数2不就没什么含义了么(因为这个参数2是可以获取到的所有的context集合),如果通过createContext来获取的话性能又和getChildContext一样了,以后回来再看看将来会怎么实现。

     writer by:大沙漠 QQ:22969969

  • 相关阅读:
    改了一下分辨率,Areo特效奇迹般的恢复了...
    此连接需要活动的Internet连接
    Apple Mac OS X每日一技巧026:Spotlight打开文件所在的文件夹
    WP7有约(八):在ListPicker控件的选择页面上播放铃声
    WP7有约(七):实现铃声设置的播放图标的效果
    WP7有约(五):回到主页
    WP7有约:一个应用的破蛋过程
    WP7有约(六):AppBarUtils使用指南
    IE与firefox事件处理
    C#试题
  • 原文地址:https://www.cnblogs.com/greatdesert/p/12697531.html
Copyright © 2011-2022 走看看