【七日打卡】浅析如何兼容新旧版 React Context

796 阅读2分钟

前言

前段时间,由于需要封装一个类 v-modelReact 组件,这个组件需要传 field 字段,此字段需要传入取值的字符串路径。此时,当在 input 中输入时,会同步修改数据源中 name;当修改数据源中 name 值时,也会同步到 input 组件。由于 div 内可能存在组件嵌套,所以就需要使用 Context。(PS:由于抽出的组件,既想让其支持新版 Context,也想让其支持旧版 Context,故作此研究。)

如何兼容新、旧 Context

对于跨级组件传递数据来说,不仅仅可通过 Context 来实现,还可以通过事件订阅来实现。 mini-create-react-context 内部就是使用事件订阅模式模拟 createContext,可能大部分人对这个三方包很陌生,但是大家对 react-router 绝对不会陌生,react-router 内部源码就是使用这个三方包来创建 Contextmini-create-react-context 内部会在不存在新版 Context 时,向外界暴露 createReactContext 方法,此方法接收 defaultValue,并返回 ProviderConsumer 两个组件。 我们先看 Provider 组件,组件内部会通过旧版 Context 给后代传入一个事件订阅器,每当组件的 props 发生变化,都会通过事件订阅器推送事件。 Consumer 组件在 componentDidMount 中通过传入的事件订阅器订阅事件,如果接收到事件,则通过 onUpdate 方法来执行 setState,更新组件。 说到这里,不得不提下旧版 Context 的问题,旧版 Context 如果在数据传输的中间组件 SCU 返回 false,则以后的组件都不会收到更新后的值,也不会触发 reRender。上面我们已经通过事件订阅解决了不会更新的问题,但是还未解决无法获取新值的问题。 mini-create-react-contextConsumer 组件内部,通过事件订阅器上 get 方法来获取新值,在Provider 组件内部又通过 set 方法去设置新值,此处恰到好处的利用了闭包解决了新旧值的传递问题。