React 源码中的依赖注入方法


Posted in Javascript onNovember 07, 2018

一、前言

依赖注入(Dependency Injection)这个概念的兴起已经有很长时间了,把这个概念融入到框架中达到出神入化境地的,非Spring莫属。然而在前端领域,似乎很少会提到这个概念,难道前端的代码就不需要解耦吗?前端的代码就没有依赖了?本文将以 React 的源码为例子,看看它是如何使用依赖注入这一设计模式的。

二、依赖注入的基本概念

在看代码之前,有必要先简单介绍一下依赖注入的基本概念。依赖注入和控制反转(Inversion of Control),这两个词经常一起出现。一句话表述他们之间的关系:依赖注入是控制反转的一种实现方式。另一种方式叫依赖查找(Dependency Lookup)。

在控制不反转的情况下,某个类如果依赖另一个类,它会自己来创建依赖:

class Person {
  eat() {
    const dinner = new Dinner('法国菜');
    console.log('开饭啦!,今晚自己做:', dinner.name);
  }
}

class Dinner {
  constructor(name) {
    this.name = name;
  }
}

假设一个人要吃饭,如果控制不反转,就需要自己来做,像上面的代码一样要自己new Dinner。

如果使用控制反转,吃什么就不用自己费脑子了,别人给我做好放到我面前,我直接吃就好!

class Person {
  eat(dinner) {
    console.log('开饭啦!,今晚有大厨给我做:', dinner.name);
  }
}

也就是说,不需要自己来创建依赖的对象了,由外部传入,这就是依赖注入!

三、React 中的依赖注入

众所周知,React 除了可以在浏览器运行外(ReactDOM),也可以制作 App 在手机端运行(ReactNative)。而两者有大量的代码都是可以共享的,这就是依赖注入的使用场景了。

我们来看下具体是如何注入的:

// ReactDOM.js
var ReactDefaultInjection = require('ReactDefaultInjection');
ReactDefaultInjection.inject();

// ReactNative.js
var ReactNativeDefaultInjection = require('ReactNativeDefaultInjection');
ReactNativeDefaultInjection.inject();

注入的位置都在框架代码最开始加载的位置。下面以 ReactDOM 为例子,详细讲解注入的逻辑。

先来看看需要注入的对象都有哪些,定义在 ReactInjection.js 这个文件当中:

var DOMProperty = require('DOMProperty');
var EventPluginHub = require('EventPluginHub');
var EventPluginUtils = require('EventPluginUtils');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactHostComponent = require('ReactHostComponent');
var ReactUpdates = require('ReactUpdates');

var ReactInjection = {
 Component: ReactComponentEnvironment.injection,
 DOMProperty: DOMProperty.injection,
 EmptyComponent: ReactEmptyComponent.injection,
 EventPluginHub: EventPluginHub.injection,
 EventPluginUtils: EventPluginUtils.injection,
 EventEmitter: ReactBrowserEventEmitter.injection,
 HostComponent: ReactHostComponent.injection,
 Updates: ReactUpdates.injection,
};

module.exports = ReactInjection;

这里面每一个 injection 都是一个对象,对象内定义了一个或多个 inject 的方法来注入对应的内容。以ReactUpdates.injection为例子:

// ReactUpdates.js
var ReactUpdatesInjection = {
  injectReconcileTransaction: function (ReconcileTransaction) {
    ...
    ReactUpdates.ReactReconcileTransaction = ReconcileTransaction;
  },

  injectBatchingStrategy: function (_batchingStrategy) {
    ...
    batchingStrategy = _batchingStrategy;
  },
};

var ReactUpdates = {
  ...
  injection: ReactUpdatesInjection,
};

可以看到 ReactUpdates 依赖的ReactReconcileTransaction和batchingStrategy就是通过这 2 个方法注入进去的。

有了上面的内容,相当于定义好需要依赖的内容了。下一步就是创建具体的依赖内容,然后注入到需要的地方:

// ReactDefaultInjection.js
var ReactInjection = require('ReactInjection');
var ReactReconcileTransaction = require('ReactReconcileTransaction');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');

...

function inject() {
  ...

  ReactInjection.Updates.injectReconcileTransaction(
    ReactReconcileTransaction
  );
  ReactInjection.Updates.injectBatchingStrategy(
    ReactDefaultBatchingStrategy
  );
}

这里的 ReactInjection.Updates 等于 ReactUpdates.injection 这个对象。而 inject 方法,就是在前文的 ReactDOM.js 中调用的方法ReactDefaultInjection.inject()。

上述各个文件整体的调用关系如下:

React 源码中的依赖注入方法

四、总结

本文介绍了依赖注入的基本概念,并结合 React 的源码讲解具体的使用场景。这样做的主要目的是解耦,可以根据实际的上下文传入不同的依赖对象,优雅的实现了代码的抽象与复用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery中nextUntil()方法用法实例
Jan 07 Javascript
JS实现上下左右对称的九九乘法表
Feb 22 Javascript
JS中使用apply方法通过不同数量的参数调用函数的方法
May 31 Javascript
Bootstrap表单使用方法详解
Feb 17 Javascript
用vue构建多页面应用的示例代码
Sep 20 Javascript
Angular移动端页面input无法输入的解决方法
Nov 14 Javascript
详解layui弹窗父子窗口之间传参数的方法
Jan 16 Javascript
浅谈React + Webpack 构建打包优化
Jan 23 Javascript
JavaScript设计模式之职责链模式应用示例
Aug 07 Javascript
js实现搜索栏效果
Nov 16 Javascript
你或许不知道的一些npm实用技巧
Jul 04 Javascript
微信小程序 腾讯地图显示偏差问题解决
Jul 27 Javascript
监听angularJs列表数据是否渲染完毕的方法示例
Nov 07 #Javascript
详解react native页面间传递数据的几种方式
Nov 07 #Javascript
微信小程序使用npm支持踩坑
Nov 07 #Javascript
Angular Material Icon使用详解
Nov 07 #Javascript
详解Webpack loader 之 file-loader
Nov 07 #Javascript
JS复杂判断的更优雅写法代码详解
Nov 07 #Javascript
javascript动态创建对象的属性详解
Nov 07 #Javascript
You might like
PHP实现自动登入google play下载app report的方法
2014/09/23 PHP
PHP实现二维数组去重功能示例
2017/01/12 PHP
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
jQuery中jqGrid分页实现代码
2011/11/04 Javascript
jQuery中animate()方法用法实例
2014/12/24 Javascript
jQuery循环动画与获取组件尺寸的方法
2015/02/02 Javascript
js实现文本框支持加减运算的方法
2015/08/19 Javascript
jQuery prototype冲突的2种解决方法(附demo示例下载)
2016/01/21 Javascript
移动端翻页插件dropload.js(支持Zepto和jQuery)
2016/07/27 Javascript
移动端js触摸事件详解
2016/09/18 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
2016/11/02 Javascript
JS实现二叉查找树的建立以及一些遍历方法实现
2017/04/17 Javascript
angular.js指令中的controller、compile与link函数的不同之处
2017/05/10 Javascript
JS 验证密码 不能为空,必须含有数字、字母、特殊字符,长度在8-12位
2017/06/21 Javascript
JS图片预加载插件详解
2017/06/21 Javascript
vue+element实现打印页面功能
2019/05/20 Javascript
在vue中使用防抖函数组件操作
2020/07/26 Javascript
python flask 多对多表查询功能
2017/06/25 Python
Flask之flask-script模块使用
2018/07/26 Python
Django Rest framework之权限的实现示例
2018/12/17 Python
python+mysql实现教务管理系统
2019/02/20 Python
python实现爬取百度图片的方法示例
2019/07/06 Python
Python selenium的基本使用方法分析
2019/12/21 Python
python温度转换华氏温度实现代码
2020/12/06 Python
马来西亚银饰品牌:JEOEL
2017/12/15 全球购物
加大码胸罩、内裤和服装:Just My Size
2019/03/21 全球购物
写给保洁员表扬信
2014/01/08 职场文书
财务会计毕业生个人求职信
2014/02/03 职场文书
平安工地建设方案
2014/05/06 职场文书
电子专业毕业生自荐信
2014/05/25 职场文书
公司人事专员岗位职责
2014/08/11 职场文书
家长给老师的感谢信
2015/01/20 职场文书
人事文员岗位职责
2015/02/04 职场文书
病房管理制度范本
2015/08/06 职场文书
Python机器学习之KNN近邻算法
2021/05/14 Python
python中Matplotlib绘制直线的实例代码
2021/07/04 Python