React5 组件之间的数据共享

React 组件中的数据流动方向是 自上而下 的,也就是说在组件树中,数据只能从父组件以属性的方式传递到子组件

父组件的数据可能是其接收到的属性,也可能是自身的内部状态

        解释:

                  React 是单项数据流

                          函数属性是子组件用来通知父组件发生了什么,它更像是子组件触发的一个事件

                          父组件可以根据业务逻辑来选择如何处理这个事件,它可以更新数据后重新传递给子组件,也可以不予理会

                  双向数据绑定

                          在双向数据绑定中,父组件将数据传递给子组件,子组件修改数据后会将数据回传同步给父组件

                          父组件是无条件接受的 

状态提升

        状态提升的意思是,当组件A需要依赖另外一个组件B的内部状态

        而他们又不是父子关系时,需要将组件B的内部 状态提升 到他们公共的祖先组件中管理,就可以通过属性接收到这份数据

        当组件B需要对数据进行变更时,可以通过函数属性来通知祖先组件对数据更新,然后重新传递给子组件

唯一数据来源

       数据唯一来源是官方推荐的数据共享原则,也是最符合 React 设计理念,与单项数据流特性相辅相成,务必遵守

       解释:

                为什么多个组件之间必须共用同一份数据,是否可以引入一个事件库,一个组件分发事件,另一个组件注册相应的事件来接收数据自己维护

                原因:

                         破坏了组件的封装性,易于复用的组件都是相对独立的,它只需要定义自己需要的数据和行为(函数属性)即可,不需要谁帮助分发事件

                         数据传递不连续,会增加项目的复杂性,当项目到一定阶段后,对这份数据的依赖会变得难以维护

                         相同的数据会有多个副本,需要保证数据同步,在增加项目的复杂性的同时也提高了出现BUG的几率

Redux

        React 是一个状态管理库,他不是专属于 React 的,但是和 React 配合很不错

        在前端应用规模比较小的时候,可以不使用任何状态管理工具,只需要使用状态提升的方式来管理应用状态即可

        为了让应用状态更直观,可以将组件作为状态总线,来管理整个应用所有的状态,对于小规模的项目是推荐的

        但是当前端应用规模比较复杂时,就需要类似 Redux 来专门进行状态管理,作用如下:

                维护一个数据仓库(store)管理整个应用的状态(state),确保数据的唯一来源

                可以通过 dispatch 方法分发一个 action ,来通知 Redux 需要对数据进行变更

                Redux 接收到 action 后可以依据 action 的类型对 state 进行相应的修改

                数据更新后 Redux 会触发注册的监听器(如:更新组件属性),完成视图更新

         类似的状态管理工具还有 MobxJS(https://mobx.js.org/),可了解一下          

组件通信——context

         React 官方不推荐使用的特性,只是实验性的API,所以暂不介绍

组件通信——ref

       每一个 React 组件都有一个特殊的属性 ref ,该属性的值可以是一个字符串,也可以是一个函数

       由于字符串形式的ref 在内部实现和实际使用中存在诸多问题,官方不推荐使用,而且可能在会被移除

       所以只需要记住在看到字符串形式的ref 属性时知道有这种方法就可以

       当 ref 属性值是一个函数

                如果组件是一个 HTML 元素兼容的 React 内部组件时(如:div、img等),函数接收其对应的原生DOM节点作为参数

               如果组件是一个以类的方式定义的组件时,函数接收该组件类的实例作为参数

                如果组件是一函数方式定义的组件,那么设置为ref 值的函数永远接收到的都是 null

      ref 与组件通信之间的关系:

                 示例:

                         class UserForm extends React.Component{

                             constructor(props){

                                 super(props)

                                 this.state={

                                     name:null,

                                     age:null

                                 }

                             }

                             formData(){

                                 return this.state

                             }

                             handleFiledChange(e){

                                  const {name,value}=e.target

                                  this.setState({

                                      [name]:value

                                  })

                             }

                             render(){

                                 return (

                                     <div>

                                           <input type="text" name="name" placeholder="Name" onChange={e=>this.handleFiledChange(e)}>

                                           <input type="text" name="age" placeholder="Age" onChange={e=>this.handleFiledChange(e)}>

                                     </div>

                                 )

                             }

                          }

                          class App extends React.Component{

                              handleSubmit(){

                                  const formData=this.form.formData()

                                  alert(`formData:${JSON.stringify(formData)}`)

                              }

                              render(){

                                  return (

                                      <div>

                                           <UserForm ref={form=>this.form=form} />

                                           <button onClick={()=>this.handleSubmit()}>Submit<button>

                                      </div>

                                  )

                              }

                          }

                          ReactDOM.render(<App/>,document.querySelector("#root"))

                示例结果:

                                                                                                                                                                 

                既然通过ref 能获取子组件的实例,所以也可以调用其他成员方法,从而获取数据

                但是这不是一个好的方式,因为作为一个组件,是需要有一定的封装性的

                它应该对外只会承诺我接受什么样的属性,但不会承诺有什么样的成员方法

                也就是说,如果 JavaScript 的类支持私有成员方法,那么React组件类中的成员方法都应该定义成私有的

               ref 有自己的使用场景,此处只是说明这种方式不适用于组件间通信

总结:使用状态提升的方式在多个组件之间共享数据,切记维持应用单向数据流和数据唯一来源原则

      





文件借鉴: http://react-china.org/t/react-react/15548


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值