美文网首页
React组件之间的通信

React组件之间的通信

作者: 留白_汉服vs插画 | 来源:发表于2018-12-13 09:34 被阅读32次

    第一次写组件,结果....

    需求要的是这样的:

    我设计组件是这样的 : 

    嗯.....没经验 , 瞎设计 . 现在好了 , 玩脱了吧 ? 数据不知道怎么传出来了吧???? 趁这个机会 , 把React组件之间的传递数据整理明白 . 

    组件之间传递数据 , 一般是三个情况 , 父亲向儿子传 , 儿子向父亲传 , 组件A传给没有关系的组件B (不过大部分是兄弟组件.)

    一、「父组件」向「子组件」传值

    一个词:props

    父组件中通过 this.state={  } 或者初始化方法,定义属性.

    父组件中通过 this.state={  } 或者初始化方法,定义属性的值以及函数 , 调用子组件的时候 , 通过对子组件属性赋值的方式 , 把父组件的属性或者函数传递给子组件 . 

    在子组件中调用父组件传过来的函数或者属性 , 可以通过this.props.属性名/函数名   就可以得到了.

    对于我的那个问题 , 嵌套层次太多 , 从外到内交流成本加深 , 通过props传值 , 就非常不方便了. 所以 , 第一 , 设计组件的时候 , 一定要结构简单 ,一定要结构简单 ,一定要结构简单. 另外组件要独立 , 嵌套来嵌套去的组件 , 是非常不适合复用的. 上面那个大组件 ,我可以断定 ,以后基本是没法子复用的 . 因为相互之间嵌套太多 . 结论:极少重用的代码片 , 就不要写成组件了 .

    二、「子组件」向「父组件」传值

    利用回调函数,可以实现子组件向父组件通信:父组件将一个函数作为 props 传递给子组件,子组件调用该回调函数,便可以向父组件通信。

    下面是演示代码:

    SubComponent.js:

    子组件调用函数cb , 函数cb在子组件中定义的 , 但是定义中是调用了props.callback() , 这个是父组件传过来的.

    父组件:通过在调用子组件的时候 , 传递属性callback向子组件传递 . 

    跨级组件通信

    跨级组件通信 , 就像上面那一样 , 父组件向子组件的子组件通信 , 跨级组件通信可以使用下面两种方式:

    1 一层一层传递props

    2 使用context对象.

    太深了 , 使用第一种方法肯定是不好的  . 贼复杂. 而且这种props并不是中间层需要的啊 . 你传给中间层 , 中间层也觉得讨厌你 . 所以三层以内, 用props . 三层以外 , 用别的方法 , 也就是context .context是一个大容器 . 把要通信的内容放到这个容器中, 不管嵌套多深 , 都可以随意取用 . 

    使用context满足以下两个条件:

    上级组件声明支持context  , 并提供一个函数来返回相应的context 对象 . 

    子组件要声明自己需要使用context .

    以下代码说明, 新建 3 个文件:父组件 App.js,子组件 Sub.js,孙组件 SubSub.js。

    App.js

    父组件里通过childContextTypes 声明可以传递给任意孩子的属性以及函数 , 并在父组件里定义这个函数 . 

    Sub.js 

    SubSub.js:

    孙子组件想要用父组件的东西 , 肯定也是先通过contextTypes声明使用父组件给任意子组件公开的属性和方法 . 

    如果是父组件向子组件单向通信,可以使用变量,如果子组件想向父组件通信,同样可以由父组件提供一个回调函数,供子组件调用,回传参数。

    在使用 context 时,有两点需要注意:

    父组件需要声明自己支持 context,并提供 context 中属性的 PropTypes

    子组件需要声明自己需要使用 context,并提供其需要使用的 context 属性的 PropTypes

    父组件需提供一个 getChildContext 函数,以返回一个初始的 context 对象

    如果组件中使用构造函数(constructor),还需要在构造函数中传入第二个参数 context,并在 super 调用父类构造函数是传入 context,否则会造成组件中无法使用 context

    改变 context 对象

    我们不应该也不能直接改变 context 对象中的属性,要想改变 context 对象,只有让其和父组件的 state 或者 props 进行关联,在父组件的 state 或 props 变化时,会自动调用 getChildContext 方法,返回新的 context 对象,而后子组件进行相应的渲染。

    修改 App.js,让 context 对象可变:

    此时,在子组件的 cb 方法中,传入相应的颜色参数,就可以改变 context 对象了,进而影响到子组件:

    context 同样可以应在无状态组件上,只需将 context 作为第二个参数传入:

    胡汉三那个是乱写的 , 应该传一个颜色回去.

    非嵌套组件间通信

    非嵌套组件,就是没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。对于非嵌套组件,可以采用下面两种方式:

    利用二者共同父组件的 context 对象进行通信

    使用自定义事件的方式

    如果采用组件间共同的父级来进行中转,会增加子组件和父组件之间的耦合度,如果组件层次较深的话,找到二者公共的父组件不是一件容易的事,当然还是那句话,也不是不可以...

    这里我们采用自定义事件的方式来实现非嵌套组件间的通信。

    我们需要使用一个 events 包:npm install events --save

    新建一个 ev.js,引入 events 包,并向外提供一个事件对象,供通信时使用:

    APP.js

    Foo.js:

    Boo.js:

    总结

    本文总结了 React 中组件的几种通信方式,分别是:

    父组件向子组件通信:使用 props

    子组件向父组件通信:使用 props 回调

    跨级组件间通信:使用 context 对象

    非嵌套组件间通信:使用事件订阅

    事实上,在组件间进行通信时,这些通信方式都可以使用,区别只在于使用相应的通信方式的复杂程度和个人喜好,选择最合适的那一个。比如,通过事件订阅模式通信不止可以应用在非嵌套组件间,还可以用于跨级组件间,非嵌套组件间通信也可以使用 context 等。关键是选择最合适的方式。

    当然,自己实现组件间的通信还是太难以管理了,因此出现了很多状态管理工具,如 flux、redux 等,使用这些工具使得组件间的通信更容易追踪和管理。

    完。

    作者:黑黢黢

    链接:https://www.jianshu.com/p/fb915d9c99c4

    來源:简书

    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    相关文章

      网友评论

          本文标题:React组件之间的通信

          本文链接:https://www.haomeiwen.com/subject/lyxnqqtx.html