一个解决组件多层嵌套传值问题的方法

#1

目的

当组件嵌套太深时,底部组件想要获取到顶部组件的值就需要层层传递,这就像A给B吐了口口水,B又吐给C,经过口口相传,最后吐给了Z,这样组件之间的耦合性会像被踢了裆之后痛到跳起来的人一样高,所以需要有个管子直接插进A和Z的嘴里,这样Z就能吃口又快又新鲜的,无需等待。

依赖

  1. Proxy
  2. React
  3. Map

特点

  1. 只读的:引用的所有值都是只读的不可更改,这样就不会出现老婆生了个孩子还不知道是谁的的情况,因为大家只能看不能动手。
  2. 懒设置proxy:引用内部的数据并不是一开始就都使用proxy,而是被访问到了才添加proxy。

Code

import React from 'react'
//直接通过引用访问其他组件的工具,并且是只读的
const _cr = new Map()
_crpHandler =  {
    //防止深层引用修改ref中的内容
    get: (obj,prop) => {
      if(typeof obj[prop] === 'object' && !(obj.constructor && obj.constructor === Proxy))return new Proxy(obj[prop],this)
      else return obj[prop]
    },
    set: () => {
      return null
    }
  }
ComponentRefs = {
    setComponentRef: (name,ref) => {
      if(name && typeof name === 'string' && ref && (ref instanceof React.Component || ref instanceof React.PureComponent) ) _cr.set(name,new Proxy(ref,_crpHandler))
      function unsetComponentRef(){
        _cr.delete(name)
      }
      return unsetComponentRef
    },
    getComponentRef: (name) => {
	      if(name && typeof name === 'string') return _cr.get(name)
    }
  }

  export default ComponentRefs

setComponentRef()

向_cr中添加中添加数据,name是键,ref是要注册的组件的引用传组件的this就行。返回值是一个方法用来清除注册的引用。

getComponentRef()

返回_cr中注册的引用,没有的话map的默认是返回undefined。

_crpHandler.get()

Proxy的handler,只返回一次proxy是不够的,这只能保证第一层指向组件的引用不被修改,但是如果出现A.b.c这样的情况就没办法了。所以通过递归可以动态的给每个引用值设置proxy防止多次间接引用的修改。

How to use

import React from 'react'
import ComponentRefs from './ComponentRefs'
calss A extends React.PureComponent {
    constructor(props){
        super(props)
        ComponentRefs.setComponentRef('A',this)
    }
}

然后我们在一个和A之间隔了n层的组件Z中使用

import React from 'react'
import ComponentRefs from './ComponentRefs'
class Z extends React.PureComponent{
    constructor(props){
        super(props)
        this.A = ComponentRefs.getComponentRef('A')
    }
}

现在你拿到了A组件的引用,就可以愉快的使用A的state或者props啦,但是你是无法修改A中的数据的,除非A组件本身提供了修改数据的方法。

!!注意!!

设置ref的时机最好在constructor中,componentDidMount由于是子组件先执行,所以有可能出现子组件需要ref而父组件还未注册的情况。

目前暂不支持函数组件,容我再想想。

与React.Context对比

你是名成熟的程序员了,应该学会自己比较。

ps:欢迎各位大佬提意见和指导