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 相关文章推荐
Flash+XML滚动新闻代码 无图片 附源码下载
Nov 22 Javascript
Javascript !!的作用
Dec 04 Javascript
JQuery动画和停止动画实例代码
Mar 01 Javascript
简介JavaScript中strike()方法的使用
Jun 08 Javascript
原生态js,鼠标按下后,经过了那些单元格的简单实例
Aug 11 Javascript
前端框架学习总结之Angular、React与Vue的比较详解
Mar 14 Javascript
Vue在页面右上角实现可悬浮/隐藏的系统菜单
May 04 Javascript
详解angular应用容器化部署
Aug 14 Javascript
JavaScript 高性能数组去重的方法
Sep 20 Javascript
微信小程序实现时间戳格式转换
Jul 20 Javascript
使用React-Router实现前端路由鉴权的示例代码
Jul 26 Javascript
nuxt.js添加环境变量,区分项目打包环境操作
Nov 06 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 开发工具
2006/12/06 PHP
解析web文件操作常见安全漏洞(目录、文件名检测漏洞)
2013/06/29 PHP
PHP结合JQueryJcrop实现图片裁切实例详解
2014/07/24 PHP
PHP实现表单提交数据的验证处理功能【防SQL注入和XSS攻击等】
2017/07/21 PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
2017/11/16 PHP
如何通过PHP实现Des加密算法代码实例
2020/05/09 PHP
javascript实现的动态添加表单元素input,button等(appendChild)
2007/11/24 Javascript
关于B/S判断浏览器断开的问题讨论
2008/10/29 Javascript
javascript 操作select下拉列表框的一点小经验
2010/03/20 Javascript
jquery URL参数判断,确定菜单样式
2010/05/31 Javascript
javascript中的继承实例代码
2011/04/27 Javascript
JavaScript的strict模式与with关键字介绍
2014/02/08 Javascript
javascript去除字符串中所有标点符号和提取纯文本的正则
2014/06/07 Javascript
javascript操作字符串的原生方法
2014/12/22 Javascript
javascript实现可拖动变色并关闭层窗口实例
2015/05/15 Javascript
jQuery表格插件datatables用法汇总
2016/03/29 Javascript
jQuery+Ajax+PHP弹出层异步登录效果(附源码下载)
2016/05/27 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
js+canvas实现动态吃豆人效果
2017/03/22 Javascript
微信小程序实现上传图片功能
2018/05/28 Javascript
vue-cli3 从搭建到优化的详细步骤
2019/01/20 Javascript
在微信小程序中保存网络图片
2019/02/12 Javascript
微信小程序封装自定义弹窗的实现代码
2019/05/08 Javascript
搭建Vue从Vue-cli到router路由护卫的实现
2019/11/14 Javascript
Python图片转换成矩阵,矩阵数据转换成图片的实例
2018/07/02 Python
python wxpython 实现界面跳转功能
2019/12/17 Python
使用python从三个角度解决josephus问题的方法
2020/03/27 Python
应聘医学检验人员自荐信
2013/09/27 职场文书
总经理秘书岗位职责
2014/03/17 职场文书
借款协议书范本
2014/04/22 职场文书
副护士长竞聘演讲稿
2014/04/30 职场文书
促销活动计划书
2014/05/02 职场文书
2014财产信托协议书范本
2014/11/18 职场文书
2014年德育工作总结
2014/11/20 职场文书
教师党员自我评价范文
2015/03/04 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP