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 相关文章推荐
在textarea中屏蔽js的某个function的javascript代码
Apr 20 Javascript
动感效果的TAB选项卡jquery 插件
Jul 09 Javascript
基于jquery的图片幻灯展示源码
Jul 15 Javascript
javaScript中slice函数用法实例分析
Jun 08 Javascript
简介BootStrap model弹出框的使用
Apr 27 Javascript
jquery插件方式实现table查询功能的简单实例
Jun 06 Javascript
jquery ztree实现右键收藏功能
Nov 20 jQuery
vue项目常用组件和框架结构介绍
Dec 24 Javascript
vue-cli+webpack项目 修改项目名称的方法
Feb 28 Javascript
vue中v-cloak解决刷新或者加载出现闪烁问题(显示变量)
Apr 20 Javascript
Electron-vue脚手架改造vue项目的方法
Oct 22 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
Jul 30 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
一个简洁的多级别论坛
2006/10/09 PHP
用PHP制作的意见反馈表源码
2007/03/11 PHP
在JavaScript中调用php程序
2009/03/09 PHP
深入理解php的MySQL连接类
2013/06/07 PHP
使用Sphinx对索引进行搜索
2013/06/25 PHP
分析PHP中单双引号的误区和双引号小隐患
2016/07/19 PHP
javascript instanceof,typeof的区别
2010/03/24 Javascript
ActiveX控件与Javascript之间的交互示例
2014/06/04 Javascript
用jquery的方法制作一个简单的导航栏
2014/06/23 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
jQuery对table表格进行增删改查
2020/12/22 Javascript
JavaScript折半查找(二分查找)算法原理与实现方法示例
2018/08/06 Javascript
Angular6使用forRoot() 注册单一实例服务问题
2019/08/27 Javascript
js实现开关灯效果
2020/03/30 Javascript
详解JavaScript 中的批处理和缓存
2020/11/19 Javascript
[02:47]3.19DOTA2发布会 国服成长历程回顾
2014/03/25 DOTA
python操作mysql数据库
2017/03/05 Python
Python3中简单的文件操作及两个简单小实例分享
2017/06/18 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
2018/03/19 Python
Python二叉树定义与遍历方法实例分析
2018/05/25 Python
python判断设备是否联网的方法
2018/06/29 Python
Django使用paginator插件实现翻页功能的实例
2018/10/24 Python
基于python3 pyQt5 QtDesignner实现窗口化猜数字游戏功能
2019/07/15 Python
Python:type、object、class与内置类型实例
2019/12/25 Python
python算的上脚本语言吗
2020/06/22 Python
详解Pandas 处理缺失值指令大全
2020/07/30 Python
美国五金商店:Ace Hardware
2018/03/27 全球购物
机电专业体育教师求职信
2013/09/21 职场文书
工作失职检讨书范文
2014/01/16 职场文书
欢迎词怎么写
2015/01/23 职场文书
婚庆公司开业主持词
2015/06/30 职场文书
小学运动会入场词
2015/07/18 职场文书
大学宣传委员竞选稿
2015/11/19 职场文书
二年级数学教学反思
2016/02/16 职场文书
SQL Server基本使用和简单的CRUD操作
2021/04/05 SQL Server
Python基础教程,Python入门教程(超详细)
2021/06/24 Python