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 相关文章推荐
javascript 获取图片颜色
Apr 05 Javascript
js 完美图片新闻轮转效果,腾讯大粤网首页图片轮转改造而来
Nov 21 Javascript
js判断变量是否未定义的代码
Mar 28 Javascript
无闪烁更新网页内容JS实现
Dec 19 Javascript
js操作iframe父子窗体示例
May 22 Javascript
jQuery实现的分子运动小球碰撞效果
Jan 27 Javascript
EasyUI创建对话框的两种方式
Aug 23 Javascript
jQuery css() 方法动态修改CSS属性
Sep 25 Javascript
微信小程序实现倒计时补零功能
Jul 09 Javascript
详解微信小程序文件下载--视频和图片
Apr 24 Javascript
JS实现页面数据懒加载
Feb 13 Javascript
Vuex实现简单购物车
Jan 10 Vue.js
监听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&mysql(四)
2006/10/09 PHP
关于Sphinx创建全文检索的索引介绍
2013/06/25 PHP
如何阻止网站被恶意反向代理访问(防网站镜像)
2014/03/18 PHP
修改Laravel5.3中的路由文件与路径
2016/08/10 PHP
PHP实现上一篇下一篇的方法实例总结
2016/09/22 PHP
php之可变函数的实例详解
2017/09/13 PHP
javaScript 读取和设置文档元素的样式属性
2009/04/14 Javascript
JQuery 获取和设置Select选项的代码
2010/02/07 Javascript
JS 对输入框进行限制(常用的都有)
2013/07/30 Javascript
IE10中flexigrid无法显示数据的解决方法
2015/07/26 Javascript
jQuery实现的经典竖向伸缩菜单效果代码
2015/09/24 Javascript
Js 获取、判断浏览器版本信息的简单方法
2016/08/08 Javascript
angularjs 源码解析之scope
2016/08/22 Javascript
[原创]JavaScript语法高亮插件highlight.js用法详解【附highlight.js本站下载】
2016/11/01 Javascript
AngularJS的脏检查深入分析
2017/04/22 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
微信小程序返回多级页面的实现方法
2017/10/27 Javascript
js canvas实现红包照片效果
2018/08/21 Javascript
vue左侧菜单,树形图递归实现代码
2018/08/24 Javascript
详解SPA中前端路由基本原理与实现方式
2018/09/12 Javascript
js屏蔽F12审查元素,禁止修改页面代码等实现代码
2020/10/02 Javascript
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
python时间日期函数与利用pandas进行时间序列处理详解
2018/03/13 Python
python利用smtplib实现QQ邮箱发送邮件
2020/05/20 Python
PyCharm2020.3.2安装超详细教程
2021/02/08 Python
Python Spyder 调出缩进对齐线的操作
2021/02/26 Python
CSS3中的Transition过度与Animation动画属性使用要点
2016/05/20 HTML / CSS
HTML5实现桌面通知 提示功能
2017/10/11 HTML / CSS
精彩的大学生自我评价
2013/11/17 职场文书
大学生社会实践自我鉴定
2014/03/24 职场文书
小学家长评语大全
2014/04/16 职场文书
田径运动会通讯稿
2014/09/13 职场文书
2014年财务工作自我评价
2014/09/23 职场文书
房贷工资证明范本
2015/06/12 职场文书
php实现自动生成验证码的实例讲解
2021/11/17 PHP
NoSQL优缺点与MongoDB数据库简介
2022/06/05 MongoDB